class QadMapTool(QgsMapTool):
      
   def __init__(self, plugIn):        
      QgsMapTool.__init__(self, plugIn.iface.mapCanvas())
      self.plugIn = plugIn
      self.iface = self.plugIn.iface
      self.canvas = self.plugIn.iface.mapCanvas()      
      self.cursor = QCursor(Qt.BlankCursor)
      self.__csrRubberBand = QadCursorRubberBand(self.canvas, QadCursorTypeEnum.BOX | QadCursorTypeEnum.CROSS)
      self.entitySet = QadEntitySet()
      self.entitySetGripPoints = QadEntitySetGripPoints(plugIn)
   
      self.gripPopupMenu = None
      self.timerForGripMenu = QTimer()
      self.timerForGripMenu.setSingleShot(True)

   def __del__(self):
      self.removeItems()


   def removeItems(self):      
      if self.__csrRubberBand is not None:
         self.__csrRubberBand.removeItems() # prima lo stacco dal canvas altrimenti non si rimuove perchè usato da canvas
         del self.__csrRubberBand
         __csrRubberBand = None
      self.entitySet.clear()
      self.entitySetGripPoints.removeItems()


   def UpdatedVariablesEvent(self):
      # aggiorna in base alle nuove impostazioni delle variabili
      self.removeItems() 
      self.__csrRubberBand = QadCursorRubberBand(self.canvas, QadCursorTypeEnum.BOX | QadCursorTypeEnum.CROSS)


   def clearEntitySet(self):
      self.entitySet.deselectOnLayer()
      self.entitySet.clear()


   def clearEntityGripPoints(self):
      self.entitySetGripPoints.removeItems() # svuoto la lista


   def refreshEntityGripPoints(self, entitySet = None):
      if entitySet is None:
         entitySet = self.entitySet
      
      gripObjLimit = QadVariables.get(QadMsg.translate("Environment variables", "GRIPOBJLIMIT"))
      if gripObjLimit != 0: #  When set to 0, grips are always displayed.
         if entitySet.count() > gripObjLimit:
            # Suppresses the display of grips when the selection set includes more than the specified number of objects
            self.clearEntityGripPoints()
            return
      
      # cancello i grip delle entità che non sono in entitySet o che non sono in layer vettoriali modificabili
      i = self.entitySetGripPoints.count() - 1
      while i >= 0:
         entityGripPoint = self.entitySetGripPoints.entityGripPoints[i]
         if entitySet.containsEntity(entityGripPoint.entity) == False or \
            entityGripPoint.entity.layer.type() != QgsMapLayer.VectorLayer or entityGripPoint.entity.layer.isEditable() == False:
            self.entitySetGripPoints.entityGripPoints[i].removeItems() # lo stacco dal canvas
            del self.entitySetGripPoints.entityGripPoints[i]
         i = i - 1
      
      entity = QadEntity()
      for layerEntitySet in entitySet.layerEntitySetList:
         # considero solo i layer vettoriali che sono modificabili
         layer = layerEntitySet.layer
         if layer.type() == QgsMapLayer.VectorLayer and layer.isEditable():
            for featureId in layerEntitySet.featureIds:
               entity.set(layer, featureId)
               self.entitySetGripPoints.addEntity(entity, QadVariables.get(QadMsg.translate("Environment variables", "GRIPS")))
      

   #============================================================================
   # INIZIO - eventi per il mouse
   #============================================================================

   
   def canvasPressEvent(self, event):
      # volevo mettere questo evento nel canvasReleaseEvent
      # ma il tasto destro non genera quel tipo di evento
      if event.button() == Qt.RightButton:
         self.displayPopupMenuOnQuiescentState(event.pos())
      elif event.button() == Qt.LeftButton:
         # verifico se tasto shift premuto
         shiftKey = True if event.modifiers() & Qt.ShiftModifier else False
         # posizione corrente del mouse
         point = self.toMapCoordinates(event.pos())
         # leggo il punto grip che si interseca alla posizione del mouse
         entityGripPoint = self.entitySetGripPoints.isIntersecting(point)
         if entityGripPoint is not None:
            if shiftKey == False: # lancio il comando
               selectedEntityGripPoints = self.entitySetGripPoints.getSelectedEntityGripPoints()
               # se non ci sono già grip selezionati
               if len(selectedEntityGripPoints) == 0:
                  # seleziono il corrente
                  if self.entitySetGripPoints.selectIntersectingGripPoints(point) > 0:
                     selectedEntityGripPoints = self.entitySetGripPoints.getSelectedEntityGripPoints()

               # lancio il comando
               self.plugIn.runCommand("QadVirtualGripCommandsClass", [QadVirtualGripCommandsEnum.STRECTH, \
                                      self.entitySetGripPoints, entityGripPoint.getPoint()])
            else: # shift premuto
               # inverto lo stato ai grip che intersecano il punto 
               self.entitySetGripPoints.toggleSelectIntersectingGripPoints(point)
         else:
            result = qad_utils.getEntSel(event.pos(), self, \
                                         QadVariables.get(QadMsg.translate("Environment variables", "PICKBOX")))
            if result is not None:
               feature = result[0]
               layer = result[1]
               tmpEntity = QadEntity()
               tmpEntity.set(layer, feature.id())
               SSGetClass = QadSSGetClass(self.plugIn)
               SSGetClass.entitySet.set(self.entitySet)
               SSGetClass.elaborateEntity(tmpEntity, shiftKey)
               self.plugIn.showMsg("\n", True) # ripete il prompt
               self.entitySet.set(SSGetClass.entitySet)
               del SSGetClass # che deseleziona gli oggetti
               self.entitySet.selectOnLayer(False)
               self.refreshEntityGripPoints(self.entitySet)
            else:
               self.plugIn.runCommand("QadVirtualSelCommandClass", point)
               

   def canvasDoubleClickEvent(self,event):
      pass


   def canvasMoveEvent(self, event):
      self.timerForGripMenu.stop()
      point = self.toMapCoordinates(event.pos())
      self.__csrRubberBand.moveEvent(point)
      # hover grip points
      if self.entitySetGripPoints.hoverIntersectingGripPoints(point) == 1:
         # Specifica i metodi di accesso per le opzioni dei grip multifunzionali.
         # se > 1 devono essere mostrati i menu dinamici 
         if QadVariables.get(QadMsg.translate("Environment variables", "GRIPMULTIFUNCTIONAL")) > 1:
            for entityGripPoint in self.entitySetGripPoints.entityGripPoints:
               for gripPoint in entityGripPoint.gripPoints:
                  if gripPoint.isIntersecting(point) and gripPoint.getStatus() == QadGripStatusEnum.HOVER:
                     pos = QPoint(event.pos().x(), event.pos().y())
                     shot = lambda: self.displayPopupMenuOnGrip(pos, entityGripPoint.entity, gripPoint)
                     
                     del self.timerForGripMenu
                     self.timerForGripMenu = QTimer()
                     self.timerForGripMenu.setSingleShot(True)
                     self.timerForGripMenu.timeout.connect(shot)
                     self.timerForGripMenu.start(1000) # 1 sec
                     return
   
#          # se non ci sono grip point selezionati
#          if len(self.entitySetGripPoints.getSelectedEntityGripPoints()) == 0:
#             # leggo il punto grip che si interseca alla posizione del mouse
#             entityGripPoint = self.entitySetGripPoints.isIntersecting(point)
#             if entityGripPoint is not None:               
#                # leggo il primo punto di grip che interseca point (in map coordinate)
#                gripPoint = entityGripPoint.isIntersecting(point)
               

   def canvasReleaseEvent(self, event):
      pass

   
   #============================================================================
   # FINE - eventi per il mouse
   # INIZIO - eventi per la tastiera
   #============================================================================


   def keyPressEvent(self, event):
      self.plugIn.keyPressEvent(event)


   def keyReleaseEvent(self, event):
      pass


   #============================================================================
   # FINE - eventi per la tastiera
   # INIZIO - eventi per la rotella
   #============================================================================


   def wheelEvent(self, event):
      QgsMapTool.wheelEvent(self, event)
      self.__csrRubberBand.moveEvent(self.toMapCoordinates(event.pos()))


   #============================================================================
   # FINE - eventi per la rotella
   #============================================================================

   
   def activate(self):
      self.canvas.setToolTip("")
      self.canvas.setCursor(self.cursor)
      # posizione corrente del mouse
      self.__csrRubberBand.moveEvent(self.toMapCoordinates(self.canvas.mouseLastXY()))
      self.__csrRubberBand.show()
      self.entitySet.initByCurrentQgsSelectedFeatures(qad_utils.getVisibleVectorLayers(self.canvas)) # Tutti i layer vettoriali visibili
      self.refreshEntityGripPoints(self.entitySet)

      self.plugIn.QadCommands.continueCommandFromMapTool()
   
   def deactivate(self):
      self.__csrRubberBand.hide()
      self.timerForGripMenu.stop()
      
   def isTransient(self):
      return False # questo tool non fa zoom o pan

   def isEditTool(self):
      return False # questo tool non fa editing


   #============================================================================
   # displayPopupMenuOnQuiescentState
   #============================================================================
   def displayPopupMenuOnQuiescentState(self, pos):
      popupMenu = QMenu(self.canvas)
      history = self.plugIn.cmdsHistory
      isLastCmdToInsert = True
      isRecentMenuToInsert = True
      
      historyLen = len(history)
      i = historyLen - 1
      cmdInputHistoryMax = QadVariables.get(QadMsg.translate("Environment variables", "CMDINPUTHISTORYMAX"))
      while i >= 0 and (historyLen - i) <= cmdInputHistoryMax:
         cmdName = history[i]
         i = i - 1
         cmd = self.plugIn.QadCommands.getCommandObj(cmdName)
         if cmd is not None:
            if isLastCmdToInsert:
               isLastCmdToInsert = False
               msg = QadMsg.translate("Popup_menu_graph_window", "Repeat ") + cmd.getName()
               icon = cmd.getIcon()
               if icon is None:
                  lastCmdAction = QAction(msg, popupMenu)
               else:
                  lastCmdAction = QAction(icon, msg, popupMenu)
               cmd.connectQAction(lastCmdAction)
               popupMenu.addAction(lastCmdAction)
            else:
               if isRecentMenuToInsert:
                  isRecentMenuToInsert = False
                  recentCmdsMenu = popupMenu.addMenu(QadMsg.translate("Popup_menu_graph_window", "Recent commands"))

               icon = cmd.getIcon()
               if icon is None:
                  recentCmdAction = QAction(cmd.getName(), recentCmdsMenu)
               else:
                  recentCmdAction = QAction(icon, cmd.getName(), recentCmdsMenu)                  
               cmd.connectQAction(recentCmdAction)      
               recentCmdsMenu.addAction(recentCmdAction)

            
      if isLastCmdToInsert == False: # menu non vuoto
         popupMenu.addSeparator()

      # aggiungo comando "OPTIONS"
      cmd = self.plugIn.QadCommands.getCommandObj(QadMsg.translate("Command_list", "OPTIONS"))
      icon = cmd.getIcon()
      if icon is None:
         optionsCmdAction = QAction(cmd.getName(), popupMenu)
      else:
         optionsCmdAction = QAction(icon, cmd.getName(), popupMenu)
      cmd.connectQAction(optionsCmdAction)
      popupMenu.addAction(optionsCmdAction)
         
      popupMenu.popup(self.canvas.mapToGlobal(pos))


   #============================================================================
   # runCmdFromPopupMenuOnGrip
   #============================================================================
   def runCmdFromPopupMenuOnGrip(self, virtualGripCommand, gripPoint):
      # seleziona il grip
      gripPoint.select()
      # lancio il comando
      self.plugIn.runCommand("QadVirtualGripCommandsClass", [virtualGripCommand, self.entitySetGripPoints, gripPoint.getPoint()])


   #============================================================================
   # displayPopupMenuOnGrip
   #============================================================================
   def displayPopupMenuOnGrip(self, pos, entity, gripPoint):
      if self.gripPopupMenu is not None:
         self.gripPopupMenu.hide()
         del self.gripPopupMenu
         self.gripPopupMenu = None
         
      popupMenu = QadGripPopupMenu(self.canvas)
      
      found = False
      
      # verifico se l'entità appartiene ad uno stile di quotatura
      if entity.isDimensionComponent():
         pass
      else:
         entityType = entity.getEntityType(gripPoint.atGeom, gripPoint.atSubGeom)
         if entityType == QadEntityGeomTypeEnum.ARC:
            arc = entity.getQadGeom(gripPoint.atGeom, gripPoint.atSubGeom)
            
            # se punti finali
            if gripPoint.isIntersecting(arc.getStartPt()) or gripPoint.isIntersecting(arc.getEndPt()):
               found = True
               msg = QadMsg.translate("Popup_menu_grip_window", "Stretch")
               action = QAction(msg, popupMenu)
               f = lambda : self.runCmdFromPopupMenuOnGrip(QadVirtualGripCommandsEnum.STRECTH, gripPoint)
               QObject.connect(action, SIGNAL("triggered()"), f)
               popupMenu.addAction(action)

               msg = QadMsg.translate("Popup_menu_grip_window", "Lengthen")
               action = QAction(msg, popupMenu)
               f = lambda : self.runCmdFromPopupMenuOnGrip(QadVirtualGripCommandsEnum.LENGTHEN, gripPoint)
               QObject.connect(action, SIGNAL("triggered()"), f)
               popupMenu.addAction(action)
            # se punto medio
            elif gripPoint.isIntersecting(entity.qadGeom.getMiddlePt()):
               found = True
               msg = QadMsg.translate("Popup_menu_grip_window", "Stretch")
               action = QAction(msg, popupMenu)
               f = lambda : self.runCmdFromPopupMenuOnGrip(QadVirtualGripCommandsEnum.STRECTH, gripPoint)
               QObject.connect(action, SIGNAL("triggered()"), f)
               popupMenu.addAction(action)
               
               msg = QadMsg.translate("Popup_menu_grip_window", "Radius")
               action = QAction(msg, popupMenu)
               f = lambda : self.runCmdFromPopupMenuOnGrip(QadVirtualGripCommandsEnum.CHANGE_RADIUS, gripPoint)
               QObject.connect(action, SIGNAL("triggered()"), f)
               popupMenu.addAction(action)
            
               msg = QadMsg.translate("Popup_menu_grip_window", "Convert to line")
               action = QAction(msg, popupMenu)
               f = lambda : self.runCmdFromPopupMenuOnGrip(QadVirtualGripCommandsEnum.ARC_TO_LINE, gripPoint)
               QObject.connect(action, SIGNAL("triggered()"), f)
               popupMenu.addAction(action)
               
         elif entityType == QadEntityGeomTypeEnum.LINESTRING:
            linearObjectList = entity.getQadGeom(gripPoint.atGeom, gripPoint.atSubGeom)
            isClosed = linearObjectList.isClosed()
            nVertex = 0
            found = False
            while nVertex < linearObjectList.qty():
               linearObject = linearObjectList.getLinearObjectAt(nVertex)

               if gripPoint.isIntersecting(linearObject.getStartPt()):
                  found = True
                  msg = QadMsg.translate("Popup_menu_grip_window", "Stretch vertex")
                  action = QAction(msg, popupMenu)
                  f = lambda : self.runCmdFromPopupMenuOnGrip(QadVirtualGripCommandsEnum.STRECTH, gripPoint)
                  QObject.connect(action, SIGNAL("triggered()"), f)
                  popupMenu.addAction(action)
                  
                  # punto iniziale
                  if isClosed == False and nVertex == 0:
                     msg = QadMsg.translate("Popup_menu_grip_window", "Lengthen")
                     action = QAction(msg, popupMenu)
                     f = lambda : self.runCmdFromPopupMenuOnGrip(QadVirtualGripCommandsEnum.LENGTHEN, gripPoint)
                     QObject.connect(action, SIGNAL("triggered()"), f)
                     popupMenu.addAction(action)

                  msg = QadMsg.translate("Popup_menu_grip_window", "Add vertex")
                  action = QAction(msg, popupMenu)
                  f = lambda : self.runCmdFromPopupMenuOnGrip(QadVirtualGripCommandsEnum.ADD_VERTEX, gripPoint)
                  QObject.connect(action, SIGNAL("triggered()"), f)
                  popupMenu.addAction(action)

                  msg = QadMsg.translate("Popup_menu_grip_window", "Add vertex before")
                  action = QAction(msg, popupMenu)
                  f = lambda : self.runCmdFromPopupMenuOnGrip(QadVirtualGripCommandsEnum.ADD_VERTEX_BEFORE, gripPoint)
                  QObject.connect(action, SIGNAL("triggered()"), f)
                  popupMenu.addAction(action)
                  break
               
               # punto medio
               if gripPoint.isIntersecting(linearObject.getMiddlePt()):
                  found = True
                  msg = QadMsg.translate("Popup_menu_grip_window", "Stretch")
                  action = QAction(msg, popupMenu)
                  f = lambda : self.runCmdFromPopupMenuOnGrip(QadVirtualGripCommandsEnum.STRECTH, gripPoint)
                  QObject.connect(action, SIGNAL("triggered()"), f)
                  popupMenu.addAction(action)

                  msg = QadMsg.translate("Popup_menu_grip_window", "Add vertex")
                  action = QAction(msg, popupMenu)
                  f = lambda : self.runCmdFromPopupMenuOnGrip(QadVirtualGripCommandsEnum.ADD_VERTEX, gripPoint)
                  QObject.connect(action, SIGNAL("triggered()"), f)
                  popupMenu.addAction(action)

                  msg = QadMsg.translate("Popup_menu_grip_window", "Add vertex before")
                  action = QAction(msg, popupMenu)
                  f = lambda : self.runCmdFromPopupMenuOnGrip(QadVirtualGripCommandsEnum.ADD_VERTEX_BEFORE, gripPoint)
                  QObject.connect(action, SIGNAL("triggered()"), f)
                  popupMenu.addAction(action)
                  
                  if linearObject.isSegment(): # linea
                     msg = QadMsg.translate("Popup_menu_grip_window", "Convert to arc")
                     action = QAction(msg, popupMenu)
                     f = lambda : self.runCmdFromPopupMenuOnGrip(QadVirtualGripCommandsEnum.LINE_TO_ARC, gripPoint)
                  else: # arco
                     msg = QadMsg.translate("Popup_menu_grip_window", "Convert to line")
                     action = QAction(msg, popupMenu)
                     f = lambda : self.runCmdFromPopupMenuOnGrip(QadVirtualGripCommandsEnum.ARC_TO_LINE, gripPoint)
                  QObject.connect(action, SIGNAL("triggered()"), f)
                  popupMenu.addAction(action)
                  break
               
               nVertex = nVertex + 1
               
            linearObject = linearObjectList.getLinearObjectAt(-1) # ultima parte
            if not found and isClosed == False:
               # punto finale
               if gripPoint.isIntersecting(linearObject.getEndPt()):
                  found = True
                  msg = QadMsg.translate("Popup_menu_grip_window", "Stretch vertex")
                  action = QAction(msg, popupMenu)
                  f = lambda : self.runCmdFromPopupMenuOnGrip(QadVirtualGripCommandsEnum.STRECTH, gripPoint)
                  QObject.connect(action, SIGNAL("triggered()"), f)
                  popupMenu.addAction(action)

                  msg = QadMsg.translate("Popup_menu_grip_window", "Lengthen")
                  action = QAction(msg, popupMenu)
                  f = lambda : self.runCmdFromPopupMenuOnGrip(QadVirtualGripCommandsEnum.LENGTHEN, gripPoint)
                  QObject.connect(action, SIGNAL("triggered()"), f)
                  popupMenu.addAction(action)

                  msg = QadMsg.translate("Popup_menu_grip_window", "Add vertex")
                  action = QAction(msg, popupMenu)
                  f = lambda : self.runCmdFromPopupMenuOnGrip(QadVirtualGripCommandsEnum.ADD_VERTEX, gripPoint)
                  QObject.connect(action, SIGNAL("triggered()"), f)
                  popupMenu.addAction(action)

                  msg = QadMsg.translate("Popup_menu_grip_window", "Add vertex before")
                  action = QAction(msg, popupMenu)
                  f = lambda : self.runCmdFromPopupMenuOnGrip(QadVirtualGripCommandsEnum.ADD_VERTEX_BEFORE, gripPoint)
                  QObject.connect(action, SIGNAL("triggered()"), f)
                  popupMenu.addAction(action)

            if isClosed == False: # polyline
               # ci devono essere almeno 2 parti
               if linearObjectList.qty() >= 2:
                  msg = QadMsg.translate("Popup_menu_grip_window", "Remove vertex")
                  action = QAction(msg, popupMenu)
                  f = lambda : self.runCmdFromPopupMenuOnGrip(QadVirtualGripCommandsEnum.REMOVE_VERTEX, gripPoint)
                  QObject.connect(action, SIGNAL("triggered()"), f)
                  popupMenu.addAction(action)
            else: # polygon
               # ci devono essere almeno 4 parti
               if linearObjectList.qty() >= 4:
                  msg = QadMsg.translate("Popup_menu_grip_window", "Remove vertex")
                  action = QAction(msg, popupMenu)
                  f = lambda : self.runCmdFromPopupMenuOnGrip(QadVirtualGripCommandsEnum.REMOVE_VERTEX, gripPoint)
                  QObject.connect(action, SIGNAL("triggered()"), f)
                  popupMenu.addAction(action)
                     
      if found: # menu non vuoto
         popupMenu.popup(self.canvas.mapToGlobal(pos))
         self.gripPopupMenu = popupMenu
         
      return None 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 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)
      elif self.commandNum == QadVirtualGripCommandsEnum.CHANGE_RADIUS:
         return QadGRIPCHANGEARCRADIUSCommandClass(self.plugIn)
      elif self.commandNum == QadVirtualGripCommandsEnum.LENGTHEN:
         return QadGRIPLENGTHENCommandClass(self.plugIn)
      elif self.commandNum == QadVirtualGripCommandsEnum.ADD_VERTEX:
         cmd = QadGRIPINSERTREMOVEVERTEXCommandClass(self.plugIn)
         cmd.setInsertVertexAfter_Mode()
         return cmd
      elif self.commandNum == QadVirtualGripCommandsEnum.ADD_VERTEX_BEFORE:
         cmd = QadGRIPINSERTREMOVEVERTEXCommandClass(self.plugIn)
         cmd.setInsertVertexBefore_Mode()
         return cmd
      elif self.commandNum == QadVirtualGripCommandsEnum.REMOVE_VERTEX:
         cmd = QadGRIPINSERTREMOVEVERTEXCommandClass(self.plugIn)
         cmd.setRemoveVertex_mode()
         return cmd
      elif self.commandNum == QadVirtualGripCommandsEnum.LINE_TO_ARC:
         cmd = QadGRIPARCLINECONVERTCommandClass(self.plugIn)
         cmd.setLineToArcConvert_Mode()
         return cmd
      elif self.commandNum == QadVirtualGripCommandsEnum.ARC_TO_LINE:
         cmd = QadGRIPARCLINECONVERTCommandClass(self.plugIn)
         cmd.setArcToLineConvert_Mode()
         return cmd
      
      return None


   def initStartCommand(self, commandNum):
      if self.currentCommand is not None:
         del self.currentCommand
         self.currentCommand = None
         
      self.commandNum = commandNum
      self.currentCommand = self.getCommand()

      if self.currentCommand is not None:
         self.currentCommand.basePt.set(self.basePt.x(), self.basePt.y())
         self.currentCommand.setSelectedEntityGripPoints(self.entitySetGripPoints)
         return True
      else:
         return False


   def initNextCommand(self):
      if self.currentCommand is not None:
         del self.currentCommand
         self.currentCommand = None
         
      if self.commandNum == QadVirtualGripCommandsEnum.STRECTH or \
         self.commandNum == QadVirtualGripCommandsEnum.LENGTHEN or \
         self.commandNum == QadVirtualGripCommandsEnum.ADD_VERTEX or \
         self.commandNum == QadVirtualGripCommandsEnum.ADD_VERTEX_BEFORE or \
         self.commandNum == QadVirtualGripCommandsEnum.REMOVE_VERTEX or \
         self.commandNum == QadVirtualGripCommandsEnum.LINE_TO_ARC or \
         self.commandNum == QadVirtualGripCommandsEnum.ARC_TO_LINE or \
         self.commandNum == QadVirtualGripCommandsEnum.CHANGE_RADIUS:
         self.commandNum = QadVirtualGripCommandsEnum.MOVE
      elif self.commandNum == QadVirtualGripCommandsEnum.MOVE:
         self.commandNum = QadVirtualGripCommandsEnum.ROTATE
      elif self.commandNum == QadVirtualGripCommandsEnum.ROTATE:
         self.commandNum = QadVirtualGripCommandsEnum.SCALE
      elif self.commandNum == QadVirtualGripCommandsEnum.SCALE:
         self.commandNum = QadVirtualGripCommandsEnum.MIRROR
      elif self.commandNum == QadVirtualGripCommandsEnum.MIRROR:
         self.commandNum = QadVirtualGripCommandsEnum.MOVE

      self.currentCommand = self.getCommand()

      if self.currentCommand is not None:
         self.currentCommand.basePt.set(self.basePt.x(), self.basePt.y())
         self.currentCommand.setSelectedEntityGripPoints(self.entitySetGripPoints)
         return True
      else:
         return False
         
         
   def run(self, msgMapTool = False, msg = None):
      if self.currentCommand is None:
         return True
      res = self.currentCommand.run(msgMapTool, msg)
      if res == True:
         if self.currentCommand.skipToNextGripCommand == True:
            if self.initNextCommand(): # attivo comando successivo
               return self.currentCommand.run(msgMapTool, msg)
         else:
            # ridisegno i grip point nelle nuove posizioni resettando quelli selezionati
            self.plugIn.tool.clearEntityGripPoints()
            self.plugIn.tool.refreshEntityGripPoints()

      return res class QadMsgClass():
   def __init__(self):
   def translate(self, context, sourceText, disambiguation = None, encoding = QCoreApplication.UnicodeUTF8, n = -1):
def qadShowPluginHelp(section = "", filename = "index", packageName = None): class QadVariableTypeEnum():
class QadAUTOSNAPEnum():
class QadINPUTSEARCHOPTIONSEnum():
class QadPOLARMODEnum():
class QadDELOBJEnum():
class QadGRIPMULTIFUNCTIONALEnum():
class QadVariableLevelEnum():
class QadVariable():
class QadVariablesClass():
   UNKNOWN = 0 # sconosciuto (non gestito da QAD)
   STRING  = 1 # caratteri
   COLOR   = 2 # colore espresso in caratteri (es. rosso = "#FF0000")
   INT     = 3 # numero intero
   FLOAT   = 4 # nmer con decimali
   BOOL    = 5 # booleano (True o False)
   DISPLAY_MARK      = 1  # Turns on the AutoSnap mark
   DISPLAY_TOOLTIPS  = 2  # Turns on the AutoSnap tooltips
   MAGNET            = 4  # Turns on the AutoSnap magnet
   POLAR_TRACKING    = 8  # Turns on polar tracking
   OBJ_SNAP_TRACKING = 16 # Turns on object snap tracking
   DISPLAY_TOOLTIPS_POLAR_OSNAP_TRACKING_ORTHO = 32 # Turns on tooltips for polar tracking, object snap tracking, and Ortho mode
   ON              = 1  # Turns off all automated keyboard features when typing at the Command prompt
   AUTOCOMPLETE    = 2  # Automatically appends suggestions as each keystroke is entered after the second keystroke
   DISPLAY_LIST    = 4  # Displays a list of suggestions as keystrokes are entered
   DISPLAY_ICON    = 8  # Displays the icon of the command or system variable, if available
   EXCLUDE_SYS_VAR = 16 # Excludes the display of system variables
   MEASURE_RELATIVE_ANGLE = 1 # if setted: Measure polar angles from selected objects (relative) 
   POLAR_TRACKING         = 2 # if setted: Use polar tracking settings in object snap tracking
   SHIFT_TO_ACQUIRE       = 8 # if setted: Press Shift to acquire object snap tracking points, if not setted
   ALL_RETAINED       =  0 # All defining geometry is retained
   DELETE_ALL         =  1 # Delete all defining geometry 
   ASK_FOR_DELETE_ALL = -1 # Ask the user for delete all defining geometry 
   ON_CTRL_CYCLE_AND_HOT_GRIPT   = 1 # Access multi-functional grips with Ctrl-cycling and the Hot Grip shortcut menu
   ON_DYNAMIC_MENU_AND_HOT_GRIPT = 2 # Access multi-functional grips with the dynamic menu and the Hot Grip shortcut menu
   GLOBAL  = 0 # variabile globale di QAD
   PROJECT = 2 # variabile del progetto corrente (che sovrascrive quella globale)
   def __init__(self, name, value, typeValue, minNum = None, maxNum = None, descr = "", level = QadVariableLevelEnum.GLOBAL):
   def __init__(self):
   def getVarNames(self):
   def set(self, VarName, varValue):
   def get(self, VarName, defaultValue = None):
   def getVariable(self, VarName):
   def getDefaultQadIniFilePath(self):
   def getDefaultQadIniFilePath(self):
   def getProjectQadIniFilePath(self):
   def __saveVariables(self, Path, filterOnLevel = None):
   def save(self, Path=""):
   def __loadVariables(self, Path, filterOnLevel = None):
   def load(self, Path=""):
   def copyTo(self, dest): 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 QadIDCommandClass(QadCommandClass):

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

   def getName(self):
      return QadMsg.translate("Command_list", "ID")

   def getEnglishName(self):
      return "ID"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runIDCommand)

   def getNote(self):
      # impostare le note esplicative del comando
      return QadMsg.translate("Command_ID", "Displays the coordinate values of a specified location.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
        
   def run(self, msgMapTool = False, msg = None):           
      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
               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

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

         self.plugIn.setLastPoint(pt)            
         self.showMsg("\n" + pt.toString())
         return True class QadSETCURRLAYERBYGRAPHCommandClass(QadCommandClass):

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

   def getName(self):
      return QadMsg.translate("Command_list", "SETCURRLAYERBYGRAPH")

   def getEnglishName(self):
      return "SETCURRLAYERBYGRAPH"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runSETCURRLAYERBYGRAPHCommand)

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/setcurrlayerbygraph.png")
   
   def getNote(self):
      # impostare le note esplicative del comando      
      return QadMsg.translate("Command_SETCURRLAYERBYGRAPH", "Sets a layer of a graphical object as current.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      self.entSelClass = None

   def __del__(self):
      QadCommandClass.__del__(self)
      if self.entSelClass is not None:
         del self.entSelClass            


   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      if self.step == 0 or self.step == 1: # quando si é in fase di selezione entità
         return self.entSelClass.getPointMapTool(drawMode)
      else:
         return QadCommandClass.getPointMapTool(self, drawMode)


   def getCurrentContextualMenu(self):
      if self.step == 0 or self.step == 1: # quando si é in fase di selezione entità
         return self.entSelClass.getCurrentContextualMenu()
      else:
         return self.contextualMenu

   
   def waitForEntsel(self, msgMapTool, msg):
      if self.entSelClass is not None:
         del self.entSelClass
         self.entSelClass = None
      self.entSelClass = QadEntSelClass(self.plugIn)
      self.entSelClass.msg = QadMsg.translate("Command_SETCURRLAYERBYGRAPH", "Select object whose layer will be the current layer: ")
      self.getPointMapTool().setSnapType(QadSnapTypeEnum.DISABLE)
      self.entSelClass.run(msgMapTool, msg)
        
   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
      
      if self.step == 0:     
         self.waitForEntsel(msgMapTool, msg)
         self.step = 1
         return False # continua
      
      elif self.step == 1:
         if self.entSelClass.run(msgMapTool, msg) == True:
            if self.entSelClass.entity.isInitialized():
               layer = self.entSelClass.entity.layer
               if self.plugIn.canvas.currentLayer() is None or \
                  self.plugIn.canvas.currentLayer() != layer:                              
                  self.plugIn.canvas.setCurrentLayer(layer)
                  self.plugIn.iface.setActiveLayer(layer) # lancia evento di deactivate e activate dei plugin
                  self.plugIn.iface.legendInterface().refreshLayerSymbology(layer)
                  msg = QadMsg.translate("Command_SETCURRLAYERBYGRAPH", "\nThe current layer is {0}.")
                  self.showMsg(msg.format(layer.name()))
               del self.entSelClass
               self.entSelClass = None
               return True
            else:               
               if self.entSelClass.canceledByUsr == True: # fine comando
                  return True
               self.showMsg(QadMsg.translate("QAD", "No geometries in this position."))
               self.waitForEntsel(msgMapTool, msg)
         return False # continua class QadSETCURRUPDATEABLELAYERBYGRAPHCommandClass(QadCommandClass):

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

   def getName(self):
      return QadMsg.translate("Command_list", "SETCURRUPDATEABLELAYERBYGRAPH")

   def getEnglishName(self):
      return "SETCURRUPDATEABLELAYERBYGRAPH"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runSETCURRUPDATEABLELAYERBYGRAPHCommand)

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/setcurrupdateablelayerbygraph.png")
   
   def getNote(self):
      # impostare le note esplicative del comando      
      return QadMsg.translate("Command_SETCURRUPDATEABLELAYERBYGRAPH", "Sets the layers of a graphical objects as editable.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      self.SSGetClass = QadSSGetClass(plugIn)
      self.firstTime = True

   def __del__(self):
      QadCommandClass.__del__(self)
      del self.SSGetClass
        
   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      if self.step == 0: # quando si é in fase di selezione entità
         return self.SSGetClass.getPointMapTool(drawMode)
      else:
         return QadCommandClass.getPointMapTool(self, drawMode)


   def getCurrentContextualMenu(self):
      if self.step == 0 or self.step == 1: # quando si é in fase di selezione entità
         return self.SSGetClass.getCurrentContextualMenu()
      else:
         return self.contextualMenu


   def run(self, msgMapTool = False, msg = None):     
      if self.step == 0: # inizio del comando   
         if self.firstTime == True:
            self.showMsg(QadMsg.translate("Command_SETCURRUPDATEABLELAYERBYGRAPH", "\nSelect objects whose layers will be the editable: "))
            self.firstTime = False
            
         if self.SSGetClass.run(msgMapTool, msg) == True:
            # selezione terminata
            self.step = 1
            return self.run(msgMapTool, msg)
         else:
            return False # continua

      elif self.step == 1: # dopo aver atteso la selezione di oggetti
         message = ""    
         for layerEntitySet in self.SSGetClass.entitySet.layerEntitySetList:
            layer = layerEntitySet.layer       
            if layer.isEditable() == False:
               if layer.startEditing() == True:
                  self.plugIn.iface.legendInterface().refreshLayerSymbology(layer)
                  self.showMsg(QadMsg.translate("Command_SETCURRUPDATEABLELAYERBYGRAPH", "\nThe layer {0} is editable.").format(layer.name()))

         if len(self.SSGetClass.entitySet.layerEntitySetList) == 1:
            layer = self.SSGetClass.entitySet.layerEntitySetList[0].layer
            if self.plugIn.canvas.currentLayer() is None or \
               self.plugIn.canvas.currentLayer() != layer:               
               self.plugIn.canvas.setCurrentLayer(layer)
               self.plugIn.iface.setActiveLayer(layer) # lancia evento di deactivate e activate dei plugin
               self.plugIn.iface.legendInterface().refreshLayerSymbology(layer)
               self.showMsg(QadMsg.translate("Command_SETCURRUPDATEABLELAYERBYGRAPH", "\nThe current layer is {0}.").format(layer.name()))
         
         return True class QadSETVARCommandClass(QadCommandClass):

   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadSETVARCommandClass(self.plugIn)
   
   def getName(self):
      return QadMsg.translate("Command_list", "SETVAR")

   def getEnglishName(self):
      return "SETVAR"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runSETVARCommand)

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/variable.png")

   def getNote(self):
      # impostare le note esplicative del comando      
      return QadMsg.translate("Command_SETVAR", "Sets the QAD environment variables.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      self.varName = ""

         
   def run(self, msgMapTool = False, msg = None):
      if self.step == 0: # inizio del comando
         # si appresta ad attendere una stringa
         self.waitForString(QadMsg.translate("Command_SETVAR", "Enter the variable name or [?]: "), \
                            QadMsg.translate("Command_SETVAR", "?"))
         self.step = 1
         return False
      elif self.step == 1: # dopo aver atteso il nome della variabile si riavvia il comando
         if msgMapTool == True: # niente può arrivare da grafica
            return False
         #  il nome della variabile arriva come parametro della funzione
         self.varName = msg
         if self.varName == QadMsg.translate("Command_SETVAR", "?"): # lista delle variabili            
            # si appresta ad attendere una stringa            
            self.waitForString(QadMsg.translate("Command_SETVAR", "Enter variable(s) to list <*>: "), \
                               QadMsg.translate("Command_SETVAR", "*"))
            self.step = 3
            return False
         else:
            variable = QadVariables.getVariable(self.varName)
            if variable is None:               
               msg = QadMsg.translate("Command_SETVAR", "\nUnknown variable. Enter {0} ? to list variable names.")
               self.showErr(msg.format(QadMsg.translate("Command_list", "SETVAR")))
               return False
            else:
               varValue = variable.value
               varDescr = variable.descr
               varType = str(type(varValue))
               if len(varDescr) > 0:
                  self.showMsg("\n" + varDescr)
               
               msg = QadMsg.translate("Command_SETVAR", "Enter new value for variable {0} <{1}>: ")
               if varType == "<type 'str'>":
                  # si appresta ad attendere una stringa
                  self.waitForString(msg.format(self.varName, varValue), varValue)
               elif varType == "<type 'int'>":
                  # si appresta ad attendere un numero intero
                  self.waitForInt(msg.format(self.varName, varValue), varValue)
               elif varType == "<type 'float'>":
                  # si appresta ad attendere un numero reale
                  self.waitForFloat(msg.format(self.varName, varValue), varValue)
               elif varType == "<type 'bool'>":
                  # si appresta ad attendere un numero reale
                  self.waitForBool(msg.format(self.varName, varValue), varValue)
               self.step = 2
               return False
      elif self.step == 2: # dopo aver atteso il valore della variabile si riavvia il comando
         if msgMapTool == True: # niente può arrivare da grafica
            return False
         # il valore della variabile arriva come parametro della funzione
         QadVariables.set(self.varName, msg)
         QadVariables.save()
         self.plugIn.UpdatedVariablesEvent()
         
         return True
      elif self.step == 3: # dopo aver atteso il nome della variabile si riavvia il comando
         if msgMapTool == True: # niente può arrivare da grafica
            return False

         if msg == "*":
            varNames = QadVariables.getVarNames()
         else:
            #  il nome della variabile arriva come parametro della funzione
            varNames = msg.strip().split(",")
            
         varNames.sort()
         for self.varName in varNames:
            self.varName = self.varName.strip()
            varValue = QadVariables.get(self.varName)
            if varValue is not None:
               msg = "\n" + self.varName + "=" + str(varValue)
               self.showMsg(msg)
               
         self.plugIn.UpdatedVariablesEvent()
               
         return True class QadPLINECommandClass(QadCommandClass):

   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadPLINECommandClass(self.plugIn)
      
   def getName(self):
      return QadMsg.translate("Command_list", "PLINE")

   def getEnglishName(self):
      return "PLINE"

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

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/pline.png")

   def getNote(self):
      # impostare le note esplicative del comando      
      return QadMsg.translate("Command_PLINE", "Creates a polyline by many methods.\n\nA polyline is a single object that is composed of line,\nand arc segments.")
   
   def __init__(self, plugIn, asToolForMPolygon = False):
      QadCommandClass.__init__(self, plugIn)
      self.vertices = []
      self.realVerticesIndexes = [] # posizioni in vertices dei vertici reali 
                                    # (l'arco è approssimato a tanti segmenti)
      self.firstVertex = True
      
      self.asToolForMPolygon = asToolForMPolygon
      if self.asToolForMPolygon:
         self.rubberBand = createRubberBand(self.plugIn.canvas, QGis.Polygon, False)
      else:
         self.rubberBand = createRubberBand(self.plugIn.canvas, QGis.Line)
         
      self.ArcPointMapTool = None
      self.mode = "LINE"
      # 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.virtualCmd = False


   def __del__(self):
      QadCommandClass.__del__(self)
      if self.ArcPointMapTool is not None:
         del self.ArcPointMapTool

      self.rubberBand.hide()
      self.plugIn.canvas.scene().removeItem(self.rubberBand)


   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      if (self.plugIn is not None):
         if self.mode == "ARC":
            if self.ArcPointMapTool is None:
               self.ArcPointMapTool = Qad_arc_maptool(self.plugIn, self.asToolForMPolygon) # se True significa che è usato per disegnare un poligono
            return self.ArcPointMapTool
         else:
            if self.PointMapTool is None:
               self.PointMapTool = Qad_pline_maptool(self.plugIn, self.asToolForMPolygon) # se True significa che è usato per disegnare un poligono
            return self.PointMapTool
      else:
         return None

   
   def setRubberBandColor(self, rubberBandBorderColor, rubberBandFillColor):
      if rubberBandBorderColor is not None:
         self.rubberBand.setBorderColor(rubberBandBorderColor)
      if rubberBandFillColor is not None:
         self.rubberBand.setFillColor(rubberBandFillColor)


   def addRealVertex(self, point):
      self.realVerticesIndexes.append(len(self.vertices))
      self.vertices.append(point)     
      self.addPointToRubberBand(point)
      self.plugIn.setLastPoint(self.vertices[-1])            
      self.plugIn.setLastSegmentAng(self.getLastSegmentAng())
      self.getPointMapTool().setPolarAngOffset(self.plugIn.lastSegmentAng)


   def delLastRealVertex(self):
      tot = len(self.realVerticesIndexes)
      if tot > 0:
         i = self.realVerticesIndexes[tot - 1]
         if tot > 1:
            iEnd = self.realVerticesIndexes[tot - 2]
         else:
            iEnd = -1
         
         del self.realVerticesIndexes[-1] # cancello ultimo vertice reale
         while i > iEnd:
            del self.vertices[-1] # cancello ultimo vertice
            self.removeLastPointToRubberBand()
            i = i - 1

         self.plugIn.setLastPoint(self.vertices[-1])            
         self.plugIn.setLastSegmentAng(self.getLastSegmentAng())
         self.getPointMapTool().setPolarAngOffset(self.plugIn.lastSegmentAng)


   def addArcVertices(self, points, inverse):
      tot = len(points)
      if inverse == False:
         i = 1 # salto il primo punto dell'arco che coincide con l'ultimo punto precedente
         while i < tot:
            self.vertices.append(points[i])     
            self.addPointToRubberBand(points[i])
            i = i + 1
      else:
         i = tot - 2 # salto l'ultimo punto dell'arco che coincide con l'ultimo punto precedente
         while i >= 0:
            self.vertices.append(points[i])     
            self.addPointToRubberBand(points[i])
            i = i - 1
                                    
      self.realVerticesIndexes.append(len(self.vertices) - 1)
      self.plugIn.setLastPoint(self.vertices[-1])            
      self.plugIn.setLastSegmentAng(self.getLastSegmentAng())
      self.getPointMapTool().setPolarAngOffset(self.plugIn.lastSegmentAng)


   def getLastSegmentAng(self):
      if len(self.vertices) < 2:
         result = self.plugIn.lastSegmentAng
      else:
         result = None
         lastVertex = self.vertices[-1] # ultimo vertice
         # verifico se ci sono archi
         arc = None
         arcList = QadArcList()
         if arcList.fromPoints(self.vertices) > 0:
            info = arcList.arcAt(len(self.vertices) - 1)
            if info is not None:
               arc = info[0]
               # se i punti sono così vicini da essere considerati uguali
               if qad_utils.ptNear(lastVertex, arc.getStartPt()):
                  result = arc.getTanDirectionOnStartPt() + math.pi
               else:
                  result = arc.getTanDirectionOnEndPt()
            
         if result is None:
            secondLastVertex = self.vertices[-2] # penultimo vertice
            result = qad_utils.getAngleBy2Pts(secondLastVertex, lastVertex)
      
      return result

   #============================================================================
   # WaitForArcMenu
   #============================================================================
   def WaitForArcMenu(self):
      # l'opzione CEnter viene tradotta in italiano in "CEntro" nel contesto "WaitForArcMenu"
      # l'opzione Undo viene tradotta in italiano in "ANNulla" nel contesto "WaitForArcMenu"
      keyWords = QadMsg.translate("Command_PLINE", "Angle") + "/" + \
                 QadMsg.translate("Command_PLINE", "CEnter", "WaitForArcMenu") + "/" + \
                 QadMsg.translate("Command_PLINE", "Close") +  "/" + \
                 QadMsg.translate("Command_PLINE", "Direction") + "/" + \
                 QadMsg.translate("Command_PLINE", "Line") + "/" + \
                 QadMsg.translate("Command_PLINE", "Radius") +  "/" + \
                 QadMsg.translate("Command_PLINE", "Second point") + "/" + \
                 QadMsg.translate("Command_PLINE", "Undo", "WaitForArcMenu")
      englishKeyWords = "Angle" + "/" + "CEnter" + "/" + "Close" + "/" + \
                        "Direction" + "/" + "Line" + "/" + "Radius" + "/" + \
                        "Second point"  + "/" + "Undo"
                 
      prompt = QadMsg.translate("Command_PLINE", "Specify the final point of the arc (hold Ctrl to switch direction) or [{0}]: ").format(keyWords)

      self.arcStartPt = self.vertices[-1] # ultimo vertice
      self.arcTanOnStartPt = self.getLastSegmentAng()
   
      # Il segmento di arco é tangente al precedente segmento della polilinea
      # uso il map tool per l'arco
      self.mode = "ARC"
      self.getPointMapTool().arcStartPt = self.arcStartPt
      self.getPointMapTool().arcTanOnStartPt = self.arcTanOnStartPt
      self.getPointMapTool().setMode(Qad_arc_maptool_ModeEnum.START_PT_TAN_KNOWN_ASK_FOR_END_PT)
      if self.asToolForMPolygon:
         self.getPointMapTool().endVertex = self.vertices[0]
      
      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 = 101
      return

   #============================================================================
   # WaitForLineMenu
   #============================================================================
   def WaitForLineMenu(self):
      # l'opzione Undo viene tradotta in italiano in "ANnulla" nel contesto "WaitForLineMenu"
      if self.firstVertex:
         keyWords = QadMsg.translate("Command_PLINE", "Arc") + "/" + \
                    QadMsg.translate("Command_PLINE", "Length") + "/" + \
                    QadMsg.translate("Command_PLINE", "Undo", "WaitForLineMenu") + "/" + \
                    QadMsg.translate("Command_PLINE", "Trace")
         englishKeyWords = "Arc" + "/" + "Length"+ "/" + "Undo" + "/" + "Trace"
      else:            
         keyWords = QadMsg.translate("Command_PLINE", "Arc") + "/" + \
                    QadMsg.translate("Command_PLINE", "Close") + "/" + \
                    QadMsg.translate("Command_PLINE", "Length") + "/" + \
                    QadMsg.translate("Command_PLINE", "Undo", "WaitForLineMenu") + "/" + \
                    QadMsg.translate("Command_PLINE", "Trace")
         englishKeyWords = "Arc" + "/" + "Close" + "/" + "Length" + "/" + "Undo"+ "/" + "Trace"
      prompt = QadMsg.translate("Command_PLINE", "Specify next point or [{0}]: ").format(keyWords)
         
      self.step = 1 # MENU PRINCIPLE

      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)


   #============================================================================
   # waitForTracePt
   #============================================================================
   def waitForTracePt(self, msgMapTool, msg):
      self.step = 3
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_pline_maptool_ModeEnum.ASK_FOR_TRACE_PT)
      self.getPointMapTool().firstPt = self.vertices[-1]
      # si appresta ad attendere un punto
      self.waitForPoint(QadMsg.translate("Command_PLINE", "Select the object in the trace end point: "))


   #============================================================================
   # addPointToRubberBand
   #============================================================================
   def addPointToRubberBand(self, point, doUpdate = True):
      numberOfVertices = self.rubberBand.numberOfVertices()
         
      if numberOfVertices == 2:
         # per un baco non ancora capito: se la linea ha solo 2 vertici e 
         # hanno la stessa x o y (linea orizzontale o verticale) 
         # la linea non viene disegnata perciò sposto un pochino la x o la y                 
         adjustedPoint = qad_utils.getAdjustedRubberBandVertex(self.rubberBand.getPoint(0, 0), point)                                                               
         self.rubberBand.addPoint(adjustedPoint, doUpdate)
      else:
         self.rubberBand.addPoint(point, doUpdate)
      
      
   #============================================================================
   # removeLastPointToRubberBand
   #============================================================================
   def removeLastPointToRubberBand(self):
      self.rubberBand.removeLastPoint()
         
         
   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

      if self.virtualCmd == False: # se si vuole veramente salvare la polylinea in un layer   
         currLayer, errMsg = qad_layer.getCurrLayerEditable(self.plugIn.canvas, QGis.Line)
         if currLayer is None:
            self.showErr(errMsg)
            return True # fine comando
      
      # RICHIESTA PRIMO PUNTO 
      if self.step == 0: # inizio del comando        
         self.getPointMapTool().setMode(Qad_pline_maptool_ModeEnum.DRAW_LINE) # imposto la linea elastica
         # si appresta ad attendere un punto o enter
         #                        msg, inputType,              default, keyWords, nessun controllo
         self.waitForPoint(QadMsg.translate("Command_PLINE", "Specify start point: "))
         self.step = 1
         return False
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA PUNTO OPPURE MENU PRINCIPALE
      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
               
               if self.getPointMapTool().rightButton == True: # se usato il tasto destro del mouse
                  if self.virtualCmd == False: # se si vuole veramente salvare la polylinea in un layer   
                     qad_layer.addLineToLayer(self.plugIn, currLayer, self.vertices)
                  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 value is None:
            if self.firstVertex:
               if self.plugIn.lastPoint is not None:
                  value = self.plugIn.lastPoint
               else:
                  return True # fine comando
            else:
               if self.virtualCmd == False: # se si vuole veramente salvare la polylinea in un layer   
                  qad_layer.addLineToLayer(self.plugIn, currLayer, self.vertices)
               return True # fine comando
            
         
         if type(value) == unicode:
            if value == QadMsg.translate("Command_PLINE", "Arc") or value == "Arc":
               self.WaitForArcMenu()
               return False
            elif value == QadMsg.translate("Command_PLINE", "Length") or value == "Length":
               # si appresta ad attendere un punto o un numero reale         
               # msg, inputType, default, keyWords, valori positivi
               # "Specificare lunghezza della linea: " 
               self.waitFor(QadMsg.translate("Command_PLINE", "Specify line length: "), \
                            QadInputTypeEnum.POINT2D | QadInputTypeEnum.FLOAT, \
                            None, "", \
                            QadInputModeEnum.NOT_NULL | QadInputModeEnum.NOT_ZERO | QadInputModeEnum.NOT_NEGATIVE)
               self.step = 2
               return False
            # l'opzione Undo viene tradotta in italiano in "ANnulla" nel contesto "WaitForLineMenu"
            elif value == QadMsg.translate("Command_PLINE", "Undo", "WaitForLineMenu") or value == "Undo":
               if len(self.vertices) >= 2:
                  self.delLastRealVertex() # cancello ultimo vertice reale
                  self.getPointMapTool().clear()
                  self.getPointMapTool().setDrawMode(QadGetPointDrawModeEnum.ELASTIC_LINE)
                  self.getPointMapTool().setTmpGeometry(QgsGeometry.fromPolyline(self.vertices)) # per lo snap aggiungo questa geometria temporanea
                  self.getPointMapTool().setStartPoint(self.vertices[-1])
               else:
                  self.showMsg(QadMsg.translate("QAD", "\nThe command has been canceled."))                                    
            elif value == QadMsg.translate("Command_PLINE", "Close") or value == "Close":
               newPt = self.vertices[0]
               self.addRealVertex(newPt) # aggiungo un nuovo vertice reale
               if self.virtualCmd == False: # se si vuole veramente salvare la polylinea in un layer   
                  qad_layer.addLineToLayer(self.plugIn, currLayer, self.vertices)
               return True # fine comando
            elif value == QadMsg.translate("Command_PLINE", "Trace") or value == "Trace":
               self.waitForTracePt(msgMapTool, msg)
               return False # continua

         elif type(value) == QgsPoint:
            self.addRealVertex(value) # aggiungo un nuovo vertice reale
            self.getPointMapTool().setTmpGeometry(QgsGeometry.fromPolyline(self.vertices)) # per lo snap aggiungo questa geometria temporanea
            self.getPointMapTool().setStartPoint(value)
            if self.asToolForMPolygon:
               self.getPointMapTool().endVertex = self.vertices[0]
         
         self.WaitForLineMenu()        
         if self.firstVertex:
            self.firstVertex = False
         
         return False
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA "Lunghezza" (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

         if type(value) == QgsPoint:
            dist = qad_utils.getDistance(self.vertices[-1], value)             
         else:
            dist = value

         newPt = qad_utils.getPolarPointByPtAngle(self.vertices[-1], self.getLastSegmentAng(), dist)
         self.addRealVertex(newPt) # aggiungo un nuovo vertice reale

         self.getPointMapTool().setTmpGeometry(QgsGeometry.fromPolyline(self.vertices)) # per lo snap aggiungo questa geometria temporanea
         self.getPointMapTool().setStartPoint(newPt)
         
         self.WaitForLineMenu()        
         
         self.step = 1 # torno al MENU PRINCIPLE
         
         return False

      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA "Selezionare l'oggetto nel punto finale di ricalco: " (da step = 1)
      elif self.step == 3:
         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:
            geom = None
            layer = None
            if self.getPointMapTool().entity.isInitialized(): # il punto arriva dal mouse
               entSelected = True
               layer = self.getPointMapTool().entity.layer
               geom = self.getPointMapTool().entity.getGeometry()
            else: # il punto arriva da tastiera
               # cerco se ci sono entità nel punto indicato considerando
               # solo layer lineari o poligono che non appartengano a quote
               layerList = []
               for layer in qad_utils.getVisibleVectorLayers(self.plugIn.canvas): # Tutti i layer vettoriali visibili
                  if layer.geometryType() == QGis.Line or layer.geometryType() == QGis.Polygon:
                     if len(QadDimStyles.getDimListByLayer(layer)) == 0:
                        layerList.append(layer)
                                     
               result = qad_utils.getEntSel(self.getPointMapTool().toCanvasCoordinates(value),
                                            self.getPointMapTool(), \
                                            QadVariables.get(QadMsg.translate("Environment variables", "PICKBOX")), \
                                            layerList)
               if result is not None:
                  feature = result[0]
                  layer = result[1]
                  geom = feature.getGeometry()

            if geom is not None and layer is not None:
               # trasformo la geometria nel crs del canvas per lavorare con coordinate piane xy
               geom = self.layerToMapCoordinates(layer, geom)
               ptEnd = qad_utils.closestVertexPtWithContext(value, geom)
               # leggo la parte di linea tra self.vertices[-1] e ptEnd
               points = qad_utils.getLinePart(geom, self.vertices[-1], ptEnd)
               if points is not None:
                  self.addArcVertices(points, False) # aggiungo i punti in ordine

         self.WaitForLineMenu()
         self.getPointMapTool().setMode(Qad_pline_maptool_ModeEnum.DRAW_LINE)
         self.getPointMapTool().setTmpGeometry(QgsGeometry.fromPolyline(self.vertices)) # per lo snap aggiungo questa geometria temporanea
         self.getPointMapTool().setStartPoint(self.vertices[-1])
         
         return False

      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA "Specificare punto finale dell'arco o [Angolo/CEntro/CHiudi/Direzione/LInea/Raggio/Secondo punto/ANNulla]: " (da step = 1)
      elif self.step == 101: # dopo aver atteso un punto 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.virtualCmd == False: # se si vuole veramente salvare la polylinea in un layer   
                     qad_layer.addLineToLayer(self.plugIn, currLayer, self.vertices)
                  return True # fine comando
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False

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

         if value is None:
            if self.virtualCmd == False: # se si vuole veramente salvare la polylinea in un layer   
               qad_layer.addLineToLayer(self.plugIn, currLayer, self.vertices)
            return True # fine comando
         
         if type(value) == unicode:
            if value == QadMsg.translate("Command_PLINE", "Angle") or value == "Angle":
               self.arcStartPt = self.vertices[-1]
               
               # imposto il map tool
               self.getPointMapTool().arcStartPt = self.arcStartPt
               self.getPointMapTool().setMode(Qad_arc_maptool_ModeEnum.START_PT_KNOWN_ASK_FOR_ANGLE)
               # si appresta ad attendere un punto o un numero reale         
               # msg, inputType, default, keyWords, isNullable
               self.waitFor(QadMsg.translate("Command_PLINE", "Specify the included angle: "), \
                            QadInputTypeEnum.POINT2D | QadInputTypeEnum.ANGLE, \
                            None, "", \
                            QadInputModeEnum.NOT_NULL | QadInputModeEnum.NOT_ZERO)
               self.step = 102
            # l'opzione CEnter viene tradotta in italiano in "CEntro" nel contesto "WaitForArcMenu"
            elif value == QadMsg.translate("Command_PLINE", "CEnter", "WaitForArcMenu") or value == "CEnter":
               self.arcStartPt = self.vertices[-1]
               
               # imposto il map tool
               self.getPointMapTool().setMode(Qad_arc_maptool_ModeEnum.NONE_KNOWN_ASK_FOR_CENTER_PT)
               # si appresta ad attendere un punto
               self.waitForPoint(QadMsg.translate("Command_PLINE", "Specify the center of the arc: "))
               self.step = 108
            elif value == QadMsg.translate("Command_PLINE", "Close") or value == "Close":
               arc = QadArc()

               if arc.fromStartEndPtsTan(self.arcStartPt, self.vertices[0], self.arcTanOnStartPt) == True:
                  points = arc.asPolyline()
                  if points is not None:
                     # se i punti sono così vicini da essere considerati uguali
                     if qad_utils.ptNear(self.arcStartPt, arc.getStartPt()):
                        self.addArcVertices(points, False) # aggiungo i punti in ordine
                     else:
                        self.addArcVertices(points, True) # aggiungo i punti in ordine inverso 
                     if self.virtualCmd == False: # se si vuole veramente salvare la polylinea in un layer   
                        qad_layer.addLineToLayer(self.plugIn, currLayer, self.vertices)

                     return True # fine comando
            elif value == QadMsg.translate("Command_PLINE", "Direction") or value == "Direction":
               self.arcStartPt = self.vertices[-1]
               
               # imposto il map tool
               self.getPointMapTool().setMode(Qad_arc_maptool_ModeEnum.START_PT_KNOWN_ASK_FOR_SECOND_PT)
               # si appresta ad attendere un punto o un numero reale         
               # msg, inputType, default, keyWords, isNullable
               self.waitFor(QadMsg.translate("Command_PLINE", "Specify the tangent direction for the start point of the arc: "), \
                            QadInputTypeEnum.POINT2D | QadInputTypeEnum.ANGLE, \
                            None, "", QadInputModeEnum.NOT_NULL)
               self.step = 112
            elif value == QadMsg.translate("Command_PLINE", "Line") or value == "Line":
               self.mode = "LINE"
               self.getPointMapTool().refreshSnapType() # riagggiorno lo snapType che può essere variato dal maptool dell'arco
               self.getPointMapTool().setDrawMode(QadGetPointDrawModeEnum.ELASTIC_LINE)
               self.getPointMapTool().setStartPoint(self.vertices[-1])      
               self.WaitForLineMenu()              
            elif value == QadMsg.translate("Command_PLINE", "Radius") or value == "Radius":
               self.arcStartPt = self.vertices[-1]
               
               # imposto il map tool
               self.getPointMapTool().setMode(Qad_arc_maptool_ModeEnum.START_PT_ANGLE_KNOWN_ASK_FOR_RADIUS)
               # si appresta ad attendere un punto o un numero reale         
               # msg, inputType, default, keyWords, valori positivi
               self.waitFor(QadMsg.translate("Command_PLINE", "Specify the radius of the arc: "), \
                            QadInputTypeEnum.POINT2D | QadInputTypeEnum.FLOAT, \
                            None, "", \
                            QadInputModeEnum.NOT_NULL | QadInputModeEnum.NOT_ZERO | QadInputModeEnum.NOT_NEGATIVE)
               self.step = 114
            elif value == QadMsg.translate("Command_PLINE", "Second point") or value == "Second point":
               self.arcStartPt = self.vertices[-1]
               
               # imposto il map tool
               self.getPointMapTool().setMode(Qad_arc_maptool_ModeEnum.START_PT_KNOWN_ASK_FOR_SECOND_PT)
               # si appresta ad attendere un punto               
               self.waitForPoint(QadMsg.translate("Command_PLINE", "Specify second point of the arc: "))
               self.step = 119
            # l'opzione Undo viene tradotta in italiano in "ANNulla" nel contesto "WaitForArcMenu"
            elif value == QadMsg.translate("Command_PLINE", "Undo", "WaitForArcMenu") or value == "Undo":
               if len(self.vertices) >= 2:
                  self.delLastRealVertex() # cancello ultimo vertice reale
                  self.getPointMapTool().clear()
                  self.getPointMapTool().setTmpGeometry(QgsGeometry.fromPolyline(self.vertices)) # per lo snap aggiungo questa geometria temporanea
                  self.getPointMapTool().setDrawMode(QadGetPointDrawModeEnum.ELASTIC_LINE)
               else:
                  self.showMsg(QadMsg.translate("QAD", "\nThe command has been canceled."))                                                      
               self.WaitForArcMenu()
         elif type(value) == QgsPoint: # é stato inserito il punto finale dell'arco
            arc = QadArc()         
            if arc.fromStartEndPtsTan(self.arcStartPt, value, self.arcTanOnStartPt) == True:
               if ctrlPressed: # cambio direzione
                  arc.inverse()
                  
               points = arc.asPolyline()
               if points is not None:
                  # se i punti sono così vicini da essere considerati uguali
                  if qad_utils.ptNear(self.arcStartPt, arc.getStartPt()):
                     self.addArcVertices(points, False) # aggiungo i punti in ordine
                  else:
                     self.addArcVertices(points, True) # aggiungo i punti in ordine inverso
                  self.getPointMapTool().setTmpGeometry(QgsGeometry.fromPolyline(self.vertices)) # per lo snap aggiungo questa geometria temporanea 
                                       
            self.WaitForArcMenu()
                       
         return False                              


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA "Specificare angolo inscritto: " (da step = 101)
      elif self.step == 102: # 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:
            self.arcAngle = qad_utils.getAngleBy2Pts(self.arcStartPt, value)             
         else:
            self.arcAngle = value

         # imposto il map tool
         self.getPointMapTool().arcAngle = self.arcAngle
         self.getPointMapTool().setMode(Qad_arc_maptool_ModeEnum.START_PT_ANGLE_KNOWN_ASK_FOR_END_PT)

         # l'opzione CEnter viene tradotta in italiano in "Centro" nel contesto "START_PT_ANGLE_KNOWN_ASK_FOR_END_PT"
         keyWords = QadMsg.translate("Command_PLINE", "CEnter", "START_PT_ANGLE_KNOWN_ASK_FOR_END_PT") + "/" + \
                    QadMsg.translate("Command_PLINE", "Radius")
         englishKeyWords = "CEnter" + "/" + "Radius"
         prompt = QadMsg.translate("Command_PLINE", "Specify the final point of the arc (hold Ctrl to switch direction) or [{0}]: ").format(keyWords)
                    
         keyWords += "_" + englishKeyWords
         # si appresta ad attendere un punto o una parola chiave         
         # msg, inputType, default, keyWords, isNullable
         self.waitFor(prompt, \
                      QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS, \
                      None, \
                      keyWords, QadInputModeEnum.NOT_NULL)
         self.step = 103

         return False


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA "Specificare punto finale dell'arco o [Centro/Raggio]: : " (da step = 102)
      elif self.step == 103: # dopo aver atteso un punto 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
                  return True # fine comando
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False

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

         if type(value) == unicode:
            # l'opzione CEnter viene tradotta in italiano in "Centro" nel contesto "START_PT_ANGLE_KNOWN_ASK_FOR_END_PT"
            if value == QadMsg.translate("Command_PLINE", "CEnter", "START_PT_ANGLE_KNOWN_ASK_FOR_END_PT") or value == "CEnter":
               # imposto il map tool
               self.getPointMapTool().setMode(Qad_arc_maptool_ModeEnum.START_PT_ANGLE_KNOWN_ASK_FOR_CENTER_PT)
               # si appresta ad attendere un punto
               self.waitForPoint(QadMsg.translate("Command_PLINE", "Specify the center of the arc (hold Ctrl to switch direction): "))
               self.step = 104
            elif value == QadMsg.translate("Command_PLINE", "Radius") or value == "Radius":
               # imposto il map tool
               self.getPointMapTool().setMode(Qad_arc_maptool_ModeEnum.START_PT_ANGLE_KNOWN_ASK_FOR_RADIUS)
               # si appresta ad attendere un punto o un numero reale         
               # msg, inputType, default, keyWords, valori positivi
               self.waitFor(QadMsg.translate("Command_PLINE", "Specify the radius of the arc: "), \
                            QadInputTypeEnum.POINT2D | QadInputTypeEnum.FLOAT, \
                            None, "", \
                            QadInputModeEnum.NOT_NULL | QadInputModeEnum.NOT_ZERO | QadInputModeEnum.NOT_NEGATIVE)
               self.step = 105
         elif type(value) == QgsPoint: # é stato inserito il punto finale dell'arco
            arc = QadArc()         
            if arc.fromStartEndPtsAngle(self.arcStartPt, value, self.arcAngle) == True:
               if ctrlPressed: # cambio direzione
                  arc.inverse()
                  
               points = arc.asPolyline()
               if points is not None:
                  # se i punti sono così vicini da essere considerati uguali
                  if qad_utils.ptNear(self.arcStartPt, arc.getStartPt()):
                     self.addArcVertices(points, False) # aggiungo i punti in ordine
                  else:
                     self.addArcVertices(points, True) # aggiungo i punti in ordine inverso 
                  self.getPointMapTool().setTmpGeometry(QgsGeometry.fromPolyline(self.vertices)) # per lo snap aggiungo questa geometria temporanea
                      
                  self.WaitForArcMenu()
                  return False

            # l'opzione CEnter viene tradotta in italiano in "Centro" nel contesto "START_PT_ANGLE_KNOWN_ASK_FOR_END_PT"
            keyWords = QadMsg.translate("Command_PLINE", "CEnter", "START_PT_ANGLE_KNOWN_ASK_FOR_END_PT") + "/" + \
                       QadMsg.translate("Command_PLINE", "Radius")
            prompt = QadMsg.translate("Command_PLINE", "Specify the final point of the arc (hold Ctrl to switch direction) or [{0}]: ").format(keyWords)

            englishKeyWords = "CEnter" + "/" + "Radius"
            keyWords += "_" + englishKeyWords
            # si appresta ad attendere un punto o una parola chiave         
            # msg, inputType, default, keyWords, isNullable
            self.waitFor(prompt, \
                         QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS, \
                         None, \
                         keyWords, QadInputModeEnum.NOT_NULL)
            
         return False


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA CENTRO DELL'ARCO (da step = 103)
      elif self.step == 104: # 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
                  return True # fine comando
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False

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

         arc = QadArc()         
         if arc.fromStartCenterPtsAngle(self.arcStartPt, value, self.arcAngle) == True:
            if ctrlPressed: # cambio direzione
               arc.inverse()

            points = arc.asPolyline()
            if points is not None:
               # se i punti sono così vicini da essere considerati uguali
               if qad_utils.ptNear(self.arcStartPt, arc.getStartPt()):
                  self.addArcVertices(points, False) # aggiungo i punti in ordine
               else:
                  self.addArcVertices(points, True) # aggiungo i punti in ordine inverso 
               self.getPointMapTool().setTmpGeometry(QgsGeometry.fromPolyline(self.vertices)) # per lo snap aggiungo questa geometria temporanea
                  
               self.WaitForArcMenu()
               return False      

         # si appresta ad attendere un punto
         self.waitForPoint(QadMsg.translate("Command_PLINE", "Specify the center of the arc: "))
                 
         return False


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA RAGGIO (da step = 103)
      elif self.step == 105: # 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:
            self.arcStartPtForRadius = value
            
            # imposto il map tool
            self.getPointMapTool().arcStartPtForRadius = self.arcStartPtForRadius
            self.getPointMapTool().setMode(Qad_arc_maptool_ModeEnum.START_PT_ANGLE_KNOWN_ASK_FOR_SECONDPTRADIUS)
         
            # si appresta ad attendere un punto
            self.waitForPoint(QadMsg.translate("Command_PLINE", "Specify second point: "))
            self.step = 106
         else:
            self.arcRadius = value
            self.plugIn.setLastRadius(self.arcRadius)

            # imposto il map tool
            self.getPointMapTool().arcRadius = self.arcRadius
            self.getPointMapTool().setMode(Qad_arc_maptool_ModeEnum.START_PT_ANGLE_RADIUS_KNOWN_ASK_FOR_CHORDDIRECTION)
            # si appresta ad attendere un punto o un numero reale         
            # msg, inputType, default, keyWords, isNullable
            msg = QadMsg.translate("Command_PLINE", "Specify the direction for the chord of the arc (hold Ctrl to switch direction) <{0}>: ")
            self.waitFor(msg.format(str(self.getLastSegmentAng())), \
                         QadInputTypeEnum.POINT2D | QadInputTypeEnum.ANGLE, \
                         None, "", QadInputModeEnum.NOT_NULL)
            self.step = 107
            
         return False                                          


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA SECONDO PUNTO DEL RAGGIO (da step = 105)
      elif self.step == 106: # 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
                  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.arcRadius = qad_utils.getDistance(self.arcStartPtForRadius, value)
         self.plugIn.setLastRadius(self.arcRadius)     

         # imposto il map tool
         self.getPointMapTool().arcRadius = self.arcRadius
         self.getPointMapTool().setMode(Qad_arc_maptool_ModeEnum.START_PT_ANGLE_RADIUS_KNOWN_ASK_FOR_CHORDDIRECTION)
         # si appresta ad attendere un punto o un numero reale         
         # msg, inputType, default, keyWords, isNullable
         msg = QadMsg.translate("Command_PLINE", "Specify the direction for the chord of the arc (hold Ctrl to switch direction) <{0}>: ")
         self.waitFor(msg.format(str(self.getLastSegmentAng())), \
                      QadInputTypeEnum.POINT2D | QadInputTypeEnum.ANGLE, \
                      None, "", QadInputModeEnum.NOT_NULL)
         self.step = 107


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DIREZIONE DELLA CORDA DELL'ARCO (da step = 106 e 107)
      elif self.step == 107: # 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
                  return True # fine comando
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False

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

         if type(value) == QgsPoint:
            self.arcChordDirection = qad_utils.getAngleBy2Pts(self.arcStartPt, value)             
         else:
            self.arcChordDirection = value
         
         arc = QadArc()
         if arc.fromStartPtAngleRadiusChordDirection(self.arcStartPt, self.arcAngle, \
                                                     self.arcRadius, self.arcChordDirection) == True:
            if ctrlPressed: # cambio direzione
               arc.inverse()
               
            points = arc.asPolyline()
            if points is not None:
               # se i punti sono così vicini da essere considerati uguali
               if qad_utils.ptNear(self.arcStartPt, arc.getStartPt()):
                  self.addArcVertices(points, False) # aggiungo i punti in ordine
               else:
                  self.addArcVertices(points, True) # aggiungo i punti in ordine inverso 
               self.getPointMapTool().setTmpGeometry(QgsGeometry.fromPolyline(self.vertices)) # per lo snap aggiungo questa geometria temporanea
                  
               self.WaitForArcMenu()
               return False      

         # imposto il map tool
         self.getPointMapTool().setMode(Qad_arc_maptool_ModeEnum.START_PT_ANGLE_RADIUS_KNOWN_ASK_FOR_CHORDDIRECTION)
         # si appresta ad attendere un punto o un numero reale         
         # msg, inputType, default, keyWords, isNullable
         msg = QadMsg.translate("Command_PLINE", "Specify the direction for the chord of the arc (hold Ctrl to switch direction) <{0}>: ")
         self.waitFor(msg.format(str(self.getLastSegmentAng())), \
                      QadInputTypeEnum.POINT2D | QadInputTypeEnum.ANGLE, \
                      None, "", QadInputModeEnum.NOT_NULL)
                 
         return False


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA CENTRO DELL'ARCO (da step = 101)
      elif self.step == 108: # 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
                  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.arcCenterPt = value

         # imposto il map tool
         self.getPointMapTool().arcCenterPt = self.arcCenterPt
         self.getPointMapTool().setMode(Qad_arc_maptool_ModeEnum.START_CENTER_PT_KNOWN_ASK_FOR_END_PT)

         keyWords = QadMsg.translate("Command_PLINE", "Angle") + "/" + \
                    QadMsg.translate("Command_PLINE", "chord Length")
         prompt = QadMsg.translate("Command_PLINE", "Specify the final point of the arc (hold Ctrl to switch direction) or [{0}]: ").format(keyWords)
         
         englishKeyWords = "Angle" + "/" + "chord Length"
         keyWords += "_" + englishKeyWords        
         # si appresta ad attendere un punto o una parola chiave         
         # msg, inputType, default, keyWords, isNullable
         self.waitFor(prompt, \
                      QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS, \
                      None, \
                      keyWords, QadInputModeEnum.NOT_NULL)
         self.step = 109      
         
         return False


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA "Specificare punto finale dell'arco o [Angolo/Lunghezza corda]: " (da step = 108)
      elif self.step == 109: # dopo aver atteso un punto 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
                  return True # fine comando
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False

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

         if type(value) == unicode:  
            if value == QadMsg.translate("Command_PLINE", "Angle") or value == "Angle":
               # imposto il map tool
               self.getPointMapTool().setMode(Qad_arc_maptool_ModeEnum.START_CENTER_PT_KNOWN_ASK_FOR_ANGLE)
               # si appresta ad attendere un punto o un numero reale         
               # msg, inputType, default, keyWords, valori <> 0
               self.waitFor(QadMsg.translate("Command_PLINE", "Specify the included angle (hold Ctrl to switch direction): "), \
                            QadInputTypeEnum.POINT2D | QadInputTypeEnum.ANGLE, \
                            None, "", \
                            QadInputModeEnum.NOT_NULL | QadInputModeEnum.NOT_ZERO)
               self.step = 110
               return False
            elif value == QadMsg.translate("Command_PLINE", "chord Length") or value == "chord Length":
               # imposto il map tool
               self.getPointMapTool().setMode(Qad_arc_maptool_ModeEnum.START_CENTER_PT_KNOWN_ASK_FOR_CHORD)
               # si appresta ad attendere un punto o un numero reale         
               # msg, inputType, default, keyWords, valori positivi
               self.waitFor(QadMsg.translate("Command_PLINE", "Specify the chord length (hold Ctrl to switch direction): "), \
                            QadInputTypeEnum.POINT2D | QadInputTypeEnum.FLOAT, \
                            None, "", \
                            QadInputModeEnum.NOT_NULL | QadInputModeEnum.NOT_ZERO | QadInputModeEnum.NOT_NEGATIVE)
               self.step = 111
               return False                              
         elif type(value) == QgsPoint: # se é stato inserito il punto finale dell'arco
            self.arcEndPt = value
                     
            arc = QadArc()         
            if arc.fromStartCenterEndPts(self.arcStartPt, self.arcCenterPt, self.arcEndPt) == True:
               if ctrlPressed: # cambio direzione
                  arc.inverse()
                  
               points = arc.asPolyline()
               if points is not None:
                  # se i punti sono così vicini da essere considerati uguali
                  if qad_utils.ptNear(self.arcStartPt, arc.getStartPt()):
                     self.addArcVertices(points, False) # aggiungo i punti in ordine
                  else:
                     self.addArcVertices(points, True) # aggiungo i punti in ordine inverso 
                  self.getPointMapTool().setTmpGeometry(QgsGeometry.fromPolyline(self.vertices)) # per lo snap aggiungo questa geometria temporanea
                     
                  self.WaitForArcMenu()
                  return False      
            
         keyWords = QadMsg.translate("Command_PLINE", "Angle") + "/" + \
                    QadMsg.translate("Command_PLINE", "chord Length")
         prompt = QadMsg.translate("Command_PLINE", "Specify the final point of the arc (hold Ctrl to switch direction) or [{0}]: ").format(keyWords)
         
         englishKeyWords = "Angle" + "/" + "chord Length"
         keyWords += "_" + englishKeyWords         
         # si appresta ad attendere un punto o una parola chiave         
         # msg, inputType, default, keyWords, isNullable
         self.waitFor(prompt, \
                      QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS, \
                      None, \
                      keyWords, QadInputModeEnum.NOT_NULL)
         return False


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA "Specificare angolo inscritto: " (da step = 109)
      elif self.step == 110: # 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
            ctrlPressed = self.getPointMapTool().ctrlKey
         else: # il punto arriva come parametro della funzione
            value = msg
            ctrlPressed = False

         if type(value) == QgsPoint:
            self.arcAngle = qad_utils.getAngleBy2Pts(self.arcCenterPt, value)             
         else:
            self.arcAngle = value

         arc = QadArc()         
         if arc.fromStartCenterPtsAngle(self.arcStartPt, self.arcCenterPt, self.arcAngle) == True:
            if ctrlPressed: # cambio direzione
               arc.inverse()
               
            points = arc.asPolyline()
            if points is not None:
               # se i punti sono così vicini da essere considerati uguali
               if qad_utils.ptNear(self.arcStartPt, arc.getStartPt()):
                  self.addArcVertices(points, False) # aggiungo i punti in ordine
               else:
                  self.addArcVertices(points, True) # aggiungo i punti in ordine inverso 
               self.getPointMapTool().setTmpGeometry(QgsGeometry.fromPolyline(self.vertices)) # per lo snap aggiungo questa geometria temporanea
                  
               self.WaitForArcMenu()
               return False      

         # si appresta ad attendere un punto o un numero reale         
         # msg, inputType, default, keyWords, isNullable
         self.waitFor(QadMsg.translate("Command_PLINE", "Specify the included angle (hold Ctrl to switch direction): "), \
                      QadInputTypeEnum.POINT2D | QadInputTypeEnum.ANGLE, \
                      None, "", \
                      QadInputModeEnum.NOT_NULL | QadInputModeEnum.NOT_ZERO)

         return False


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA "Specificare lunghezza della corda: " (da step = 109)
      elif self.step == 111: # 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
            ctrlPressed = self.getPointMapTool().ctrlKey
         else: # il punto arriva come parametro della funzione
            value = msg
            ctrlPressed = False

         if type(value) == QgsPoint:
            self.arcChord = qad_utils.getDistance(self.arcStartPt, value)             
         else:
            self.arcChord = value

         arc = QadArc()         
         if arc.fromStartCenterPtsChord(self.arcStartPt, self.arcCenterPt, self.arcChord) == True:
            if ctrlPressed: # cambio direzione
               arc.inverse()
               
            points = arc.asPolyline()
            if points is not None:
               # se i punti sono così vicini da essere considerati uguali
               if qad_utils.ptNear(self.arcStartPt, arc.getStartPt()):
                  self.addArcVertices(points, False) # aggiungo i punti in ordine
               else:
                  self.addArcVertices(points, True) # aggiungo i punti in ordine inverso 
               self.getPointMapTool().setTmpGeometry(QgsGeometry.fromPolyline(self.vertices)) # per lo snap aggiungo questa geometria temporanea
                  
               self.WaitForArcMenu()
               return False      

         # si appresta ad attendere un punto o un numero reale         
         # msg, inputType, default, keyWords, valori positivi
         self.waitFor(QadMsg.translate("Command_PLINE", "Specify the chord length (hold Ctrl to switch direction): "), \
                      QadInputTypeEnum.POINT2D | QadInputTypeEnum.FLOAT, \
                      None, "", \
                      QadInputModeEnum.NOT_NULL | QadInputModeEnum.NOT_ZERO | QadInputModeEnum.NOT_NEGATIVE)

         return False

     
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA "Specificare direzione tangente per il punto iniziale dell'arco: " (da step = 101)
      elif self.step == 112: # 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:
            self.arcTanOnStartPt = qad_utils.getAngleBy2Pts(self.arcStartPt, value)             
         else:
            self.arcTanOnStartPt = value

         # imposto il map tool
         self.getPointMapTool().arcTanOnStartPt = self.arcTanOnStartPt
         self.getPointMapTool().setMode(Qad_arc_maptool_ModeEnum.START_PT_TAN_KNOWN_ASK_FOR_END_PT)

         # si appresta ad attendere un punto
         self.waitForPoint(QadMsg.translate("Command_PLINE", "Specify the final point of the arc (hold Ctrl to switch direction): "))
         self.step = 113
         return False


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA PUNTO FINALE DELL'ARCO (da step = 112)
      elif self.step == 113: # 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
                  return True # fine comando
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False

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

         arc = QadArc()
         if arc.fromStartEndPtsTan(self.arcStartPt, value, self.arcTanOnStartPt) == True:
            if ctrlPressed: # cambio direzione
               arc.inverse()
               
            points = arc.asPolyline()
            if points is not None:
               # se i punti sono così vicini da essere considerati uguali
               if qad_utils.ptNear(self.arcStartPt, arc.getStartPt()):
                  self.addArcVertices(points, False) # aggiungo i punti in ordine
               else:
                  self.addArcVertices(points, True) # aggiungo i punti in ordine inverso 
               self.getPointMapTool().setTmpGeometry(QgsGeometry.fromPolyline(self.vertices)) # per lo snap aggiungo questa geometria temporanea
                  
               self.WaitForArcMenu()
               return False      

         # si appresta ad attendere un punto
         self.waitForPoint(QadMsg.translate("Command_PLINE", "Specify the final point of the arc (hold Ctrl to switch direction): "))
                 
         return False


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA RAGGIO (da step = 101)
      elif self.step == 114: # 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:
            self.arcStartPtForRadius = value
            
            # imposto il map tool
            self.getPointMapTool().arcStartPtForRadius = self.arcStartPtForRadius
            self.getPointMapTool().setMode(Qad_arc_maptool_ModeEnum.START_PT_ANGLE_KNOWN_ASK_FOR_SECONDPTRADIUS)
         
            # si appresta ad attendere un punto
            self.waitForPoint(QadMsg.translate("Command_PLINE", "Specify second point: "))
            self.step = 115
         else:
            self.arcRadius = value
            self.plugIn.setLastRadius(self.arcRadius)

            # imposto il map tool
            self.getPointMapTool().arcRadius = self.arcRadius
            self.getPointMapTool().setMode(Qad_arc_maptool_ModeEnum.START_PT_RADIUS_KNOWN_ASK_FOR_END_PT)
            
            keyWords = QadMsg.translate("Command_PLINE", "Angle")
            prompt = QadMsg.translate("Command_PLINE", "Specify the final point of the arc (hold Ctrl to switch direction) or [{0}]: ").format(keyWords)
            englishKeyWords = "Angle"
            keyWords += "_" + englishKeyWords
            # si appresta ad attendere un punto o un numero reale         
            # msg, inputType, default, keyWords, isNullable
            self.waitFor(prompt, \
                         QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS, \
                         None, keyWords, QadInputModeEnum.NOT_NULL)
            self.step = 116
            
         return False                                          


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA SECONDO PUNTO DEL RAGGIO (da step = 114)
      elif self.step == 115: # 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
                  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.arcRadius = qad_utils.getDistance(self.arcStartPtForRadius, value)
         self.plugIn.setLastRadius(self.arcRadius)     

         # imposto il map tool
         self.getPointMapTool().arcRadius = self.arcRadius
         self.getPointMapTool().setMode(Qad_arc_maptool_ModeEnum.START_PT_RADIUS_KNOWN_ASK_FOR_END_PT)
         
         keyWords = QadMsg.translate("Command_PLINE", "Angle")
         prompt = QadMsg.translate("Command_PLINE", "Specify the final point of the arc (hold Ctrl to switch direction) or [{0}]: ").format(keyWords)
         englishKeyWords = "Angle"
         keyWords += "_" + englishKeyWords
         # si appresta ad attendere un punto o un numero reale         
         # msg, inputType, default, keyWords, isNullable
         self.waitFor(prompt, \
                      QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS, \
                      None, keyWords, QadInputModeEnum.NOT_NULL)
         self.step = 116
      
         return False
      
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA "Specificare punto finale dell'arco o [Angolo]: " (da step = 114 o 115)
      elif self.step == 116: # dopo aver atteso un punto 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
                  return True # fine comando
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False

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

         if type(value) == unicode:
            if value == QadMsg.translate("Command_PLINE", "Angle") or value == "Angle":               
               # imposto il map tool
               self.getPointMapTool().setMode(Qad_arc_maptool_ModeEnum.START_PT_KNOWN_ASK_FOR_ANGLE)
               # si appresta ad attendere un punto o un numero reale         
               # msg, inputType, default, keyWords, isNullable
               self.waitFor(QadMsg.translate("Command_PLINE", "Specify the included angle: "), \
                            QadInputTypeEnum.POINT2D | QadInputTypeEnum.ANGLE, \
                            None, "", \
                            QadInputModeEnum.NOT_NULL | QadInputModeEnum.NOT_ZERO)
               self.step = 117
         elif type(value) == QgsPoint: # é stato inserito il punto finale dell'arco
            arc = QadArc()         
            if arc.fromStartEndPtsRadius(self.arcStartPt, value, self.arcRadius) == True:
               if ctrlPressed: # cambio direzione
                  arc.inverse()
                  
               points = arc.asPolyline()
               if points is not None:
                  # se i punti sono così vicini da essere considerati uguali
                  if qad_utils.ptNear(self.arcStartPt, arc.getStartPt()):
                     self.addArcVertices(points, False) # aggiungo i punti in ordine
                  else:
                     self.addArcVertices(points, True) # aggiungo i punti in ordine inverso 
                  self.getPointMapTool().setTmpGeometry(QgsGeometry.fromPolyline(self.vertices)) # per lo snap aggiungo questa geometria temporanea
                     
            self.WaitForArcMenu()
                       
         return False                              
      

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA "Specificare angolo inscritto: " (da step = 116)
      elif self.step == 117: # 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:
            self.arcAngle = qad_utils.getAngleBy2Pts(self.arcStartPt, value)             
         else:
            self.arcAngle = value

         # imposto il map tool
         self.getPointMapTool().arcAngle = self.arcAngle
         self.getPointMapTool().setMode(Qad_arc_maptool_ModeEnum.START_PT_ANGLE_RADIUS_KNOWN_ASK_FOR_CHORDDIRECTION)
         # si appresta ad attendere un punto o un numero reale         
         # msg, inputType, default, keyWords, isNullable
         msg = QadMsg.translate("Command_PLINE", "Specify the direction for the chord of the arc (hold Ctrl to switch direction) <{0}>: ")
         self.waitFor(msg.format(str(self.getLastSegmentAng())), \
                      QadInputTypeEnum.POINT2D | QadInputTypeEnum.ANGLE, \
                      None, "", QadInputModeEnum.NOT_NULL)
         self.step = 118

         return False


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DIREZIONE DELLA CORDA DELL'ARCO (da step = 117)
      elif self.step == 118: # 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
                  return True # fine comando
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False

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

         if type(value) == QgsPoint:
            self.arcChordDirection = qad_utils.getAngleBy2Pts(self.arcStartPt, value)             
         else:
            self.arcChordDirection = value
         
         arc = QadArc()
         if arc.fromStartPtAngleRadiusChordDirection(self.arcStartPt, self.arcAngle, \
                                                     self.arcRadius, self.arcChordDirection) == True:
            if ctrlPressed: # cambio direzione
               arc.inverse()
               
            points = arc.asPolyline()
            if points is not None:
               # se i punti sono così vicini da essere considerati uguali
               if qad_utils.ptNear(self.arcStartPt, arc.getStartPt()):
                  self.addArcVertices(points, False) # aggiungo i punti in ordine
               else:
                  self.addArcVertices(points, True) # aggiungo i punti in ordine inverso 
               self.getPointMapTool().setTmpGeometry(QgsGeometry.fromPolyline(self.vertices)) # per lo snap aggiungo questa geometria temporanea
               
               self.WaitForArcMenu()
               return False      

         # imposto il map tool
         self.getPointMapTool().setMode(Qad_arc_maptool_ModeEnum.START_PT_ANGLE_RADIUS_KNOWN_ASK_FOR_CHORDDIRECTION)
         # si appresta ad attendere un punto o un numero reale         
         # msg, inputType, default, keyWords, isNullable
         msg = QadMsg.translate("Command_PLINE", "Specify the direction for the chord of the arc (hold Ctrl to switch direction) <{0}>: ")
         self.waitFor(msg.format(str(self.getLastSegmentAng())), \
                      QadInputTypeEnum.POINT2D | QadInputTypeEnum.ANGLE, \
                      None, "", QadInputModeEnum.NOT_NULL)
                 
         return False
      
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA SECONDO PUNTO (da step = 101)
      elif self.step == 119: # dopo aver atteso un punto 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
                  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.arcSecondPt = value
         # imposto il map tool
         self.getPointMapTool().arcSecondPt = self.arcSecondPt
         self.getPointMapTool().setMode(Qad_arc_maptool_ModeEnum.START_SECOND_PT_KNOWN_ASK_FOR_END_PT)

         # si appresta ad attendere un punto
         self.waitForPoint(QadMsg.translate("Command_PLINE", "Specify the final point of the arc: "))
         self.step = 120
                  
         return False
      
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA PUNTO FINALE DELL'ARCO (da step = 119)
      elif self.step == 120: # 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
                  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.arcEndPt = value
         
         arc = QadArc()         
         if arc.fromStartSecondEndPts(self.arcStartPt, self.arcSecondPt, self.arcEndPt) == True:
            points = arc.asPolyline()
            if points is not None:
               # se i punti sono così vicini da essere considerati uguali
               if qad_utils.ptNear(self.arcStartPt, arc.getStartPt()):
                  self.addArcVertices(points, False) # aggiungo i punti in ordine
               else:
                  self.addArcVertices(points, True) # aggiungo i punti in ordine inverso 
               self.getPointMapTool().setTmpGeometry(QgsGeometry.fromPolyline(self.vertices)) # per lo snap aggiungo questa geometria temporanea
                  
               self.WaitForArcMenu()
               return False      
      
         # si appresta ad attendere un punto
         self.waitForPoint(QadMsg.translate("Command_PLINE", "Specify the final point of the arc: "))     
         return False       class QadARCCommandClass(QadCommandClass):

   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadARCCommandClass(self.plugIn)
   
   def getName(self):
      return QadMsg.translate("Command_list", "ARC")

   def getEnglishName(self):
      return "ARC"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runARCCommand)
   
   def getIcon(self):
      return QIcon(":/plugins/qad/icons/arc.png")

   def getNote(self):
      # impostare le note esplicative del comando      
      return QadMsg.translate("Command_ARC", "Draws an arc by many methods.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      self.vertices = []

   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      if (self.plugIn is not None):
         if self.PointMapTool is None:
            self.PointMapTool = Qad_arc_maptool(self.plugIn)
         return self.PointMapTool
      else:
         return None
         
   def run(self, msgMapTool = False, msg = None):
      self.isValidPreviousInput = True # per gestire il comando anche in macro
           
      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
      
      currLayer, errMsg = qad_layer.getCurrLayerEditable(self.plugIn.canvas, QGis.Line)
      if currLayer is None:
         self.showErr(errMsg)
         return True # fine comando

      #=========================================================================
      # RICHIESTA PRIMO PUNTO o CENTRO
      if self.step == 0: # inizio del comando
         # imposto il map tool
         self.getPointMapTool().setMode(Qad_arc_maptool_ModeEnum.NONE_KNOWN_ASK_FOR_START_PT)        
         keyWords = QadMsg.translate("Command_ARC", "Center")
         
         prompt = QadMsg.translate("Command_ARC", "Specify the start point of the arc or [{0}]:").format(keyWords)                 
         
         englishKeyWords = "Center"
         keyWords += "_" + englishKeyWords
         # si appresta ad attendere un punto o enter o una parola chiave         
         # msg, inputType, default, keyWords, nessun controllo di modo
         self.waitFor(prompt, \
                      QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS, \
                      None, \
                      keyWords, QadInputModeEnum.NONE)         
         self.step = 1
         
         return False

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA PRIMO PUNTO o CENTRO
      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
                  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 value is None:
            if self.plugIn.lastPoint is not None:
               value = self.plugIn.lastPoint
            else:
               return True # fine comando

         if type(value) == QgsPoint: # se é stato inserito il punto iniziale dell'arco           
            self.startPt = value
            self.plugIn.setLastPoint(value)
            
            # imposto il map tool
            self.getPointMapTool().arcStartPt = self.startPt
            self.getPointMapTool().setMode(Qad_arc_maptool_ModeEnum.START_PT_KNOWN_ASK_FOR_SECOND_PT)
                                
            keyWords = QadMsg.translate("Command_ARC", "Center") + "/" + \
                       QadMsg.translate("Command_ARC", "End")
            
            prompt = QadMsg.translate("Command_ARC", "Specify second point of the arc or [{0}]:").format(keyWords)                 
            
            englishKeyWords = "Center" + "/" + "End"
            keyWords += "_" + englishKeyWords
            # si appresta ad attendere un punto o una parola chiave         
            # msg, inputType, default, keyWords
            self.waitFor(prompt, \
                         QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS, \
                         None, \
                         keyWords, QadInputModeEnum.NONE)
            
            self.step = 2
            return False
         else: # si vuole inserire il centro dell'arco
            # imposto il map tool
            self.getPointMapTool().setMode(Qad_arc_maptool_ModeEnum.NONE_KNOWN_ASK_FOR_CENTER_PT)
            # si appresta ad attendere un punto
            self.waitForPoint(QadMsg.translate("Command_ARC", "Specify the center of the arc: "))
            
            self.step = 13
            return False

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA SECONDO PUNTO o CENTRO o FINE
      elif self.step == 2: # dopo aver atteso un punto 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
                  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) == unicode:
            if value == QadMsg.translate("Command_ARC", "Center") or value == "Center":
               # imposto il map tool
               self.getPointMapTool().setMode(Qad_arc_maptool_ModeEnum.START_PT_KNOWN_ASK_FOR_CENTER_PT)
               # si appresta ad attendere un punto
               self.waitForPoint(QadMsg.translate("Command_ARC", "Specify the center of the arc: "))
               self.step = 4           
            elif value == QadMsg.translate("Command_ARC", "End") or value == "End":
               # imposto il map tool
               self.getPointMapTool().setMode(Qad_arc_maptool_ModeEnum.START_PT_KNOWN_ASK_FOR_END_PT)
               # si appresta ad attendere un punto
               self.waitForPoint(QadMsg.translate("Command_ARC", "Specify the final point of the arc: "))
               self.step = 8     
         elif type(value) == QgsPoint: # se é stato inserito il secondo punto dell'arco            
            self.secondPt = value
            # imposto il map tool
            self.getPointMapTool().arcSecondPt = self.secondPt
            self.getPointMapTool().setMode(Qad_arc_maptool_ModeEnum.START_SECOND_PT_KNOWN_ASK_FOR_END_PT)

            # si appresta ad attendere un punto
            self.waitForPoint(QadMsg.translate("Command_ARC", "Specify the final point of the arc: "))
            self.step = 3
                  
         return False

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA PUNTO FINALE DELL'ARCO (da step = 2)
      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
                  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.endPt = value
         
         arc = QadArc()         
         if arc.fromStartSecondEndPts(self.startPt, self.secondPt, self.endPt) == True:
            self.plugIn.setLastPoint(arc.getEndPt())
            points = arc.asPolyline()
            if points is not None:
               # se i punti sono così vicini da essere considerati uguali
               if qad_utils.ptNear(self.startPt, arc.getStartPt()):
                  self.plugIn.setLastSegmentAng(arc.getTanDirectionOnEndPt())
               else:
                  self.plugIn.setLastSegmentAng(arc.getTanDirectionOnStartPt() + math.pi)
                  
               self.getPointMapTool().setPolarAngOffset(self.plugIn.lastSegmentAng)
                  
               qad_layer.addLineToLayer(self.plugIn, currLayer, points)               
               return True # fine comando
      
         # si appresta ad attendere un punto
         self.waitForPoint(QadMsg.translate("Command_ARC", "Specify the final point of the arc: "))
         self.isValidPreviousInput = False # per gestire il comando anche in macro     
         return False
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA CENTRO DELL'ARCO (da step = 2)
      elif self.step == 4: # 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
                  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.centerPt = value
         self.plugIn.setLastPoint(value)
         
         # imposto il map tool
         self.getPointMapTool().arcCenterPt = self.centerPt
         self.getPointMapTool().setMode(Qad_arc_maptool_ModeEnum.START_CENTER_PT_KNOWN_ASK_FOR_END_PT)
         
         keyWords = QadMsg.translate("Command_ARC", "Angle") + "/" + \
                    QadMsg.translate("Command_ARC", "chord Length")
                             
         prompt = QadMsg.translate("Command_ARC", "Specify the final point of the arc (hold Ctrl to switch direction) or [{0}]: ").format(keyWords)                 
                         
         englishKeyWords = "Angle" + "/" + "chord Length"
         keyWords += "_" + englishKeyWords
         # si appresta ad attendere un punto o una parola chiave         
         # msg, inputType, default, keyWords, valori nulli non ammessi
         self.waitFor(prompt, \
                      QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS, \
                      None, \
                      keyWords, QadInputModeEnum.NOT_NULL)
         
         self.step = 5
         return False
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA "Specificare punto finale dell'arco o [Angolo/Lunghezza corda]: " (da step = 4)
      elif self.step == 5: # dopo aver atteso un punto 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
                  return True # fine comando
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False

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

         if type(value) == unicode:  
            if value == QadMsg.translate("Command_ARC", "Angle") or value == "Angle":
               # imposto il map tool
               self.getPointMapTool().setMode(Qad_arc_maptool_ModeEnum.START_CENTER_PT_KNOWN_ASK_FOR_ANGLE)
               # si appresta ad attendere un punto o un numero reale         
               # msg, inputType, default, keyWords, valori nulli non ammessi
               self.waitFor(QadMsg.translate("Command_ARC", "Specify the included angle (hold Ctrl to switch direction): "), \
                            QadInputTypeEnum.POINT2D | QadInputTypeEnum.ANGLE, \
                            None, "", \
                            QadInputModeEnum.NOT_NULL | QadInputModeEnum.NOT_ZERO)
               self.step = 6
               return False                              
            elif value == QadMsg.translate("Command_ARC", "chord Length") or value == "chord Length":
               # imposto il map tool
               self.getPointMapTool().setMode(Qad_arc_maptool_ModeEnum.START_CENTER_PT_KNOWN_ASK_FOR_CHORD)
               # si appresta ad attendere un punto o un numero reale         
               # msg, inputType, default, keyWords, valori positivi
               self.waitFor(QadMsg.translate("Command_ARC", "Specify the chord length (hold Ctrl to switch direction): "), \
                            QadInputTypeEnum.POINT2D | QadInputTypeEnum.FLOAT, \
                            None, "", \
                            QadInputModeEnum.NOT_NULL | QadInputModeEnum.NOT_ZERO | QadInputModeEnum.NOT_NEGATIVE)
               self.step = 7
               return False                              
         elif type(value) == QgsPoint: # se é stato inserito il punto finale dell'arco
            self.endPt = value
                     
            arc = QadArc()
            if arc.fromStartCenterEndPts(self.startPt, self.centerPt, self.endPt) == True:
               if ctrlPressed: # cambio direzione
                  arc.inverse()
               
               self.plugIn.setLastPoint(arc.getEndPt())
               points = arc.asPolyline()
               if points is not None:
                  # se i punti sono così vicini da essere considerati uguali
                  if qad_utils.ptNear(self.startPt, arc.getStartPt()):
                     self.plugIn.setLastSegmentAng(arc.getTanDirectionOnEndPt())
                  else:
                     self.plugIn.setLastSegmentAng(arc.getTanDirectionOnStartPt() + math.pi)

                  self.getPointMapTool().setPolarAngOffset(self.plugIn.lastSegmentAng)
                  
                  qad_layer.addLineToLayer(self.plugIn, currLayer, points)               
                  return True # fine comando
            
            keyWords = QadMsg.translate("Command_ARC", "Angle") + "/" + \
                       QadMsg.translate("Command_ARC", "chord Length")
            prompt = QadMsg.translate("Command_ARC", "Specify the final point of the arc (hold Ctrl to switch direction) or [{0}]: ").format(keyWords)

            englishKeyWords = "Angle" + "/" + "chord Length"
            keyWords += "_" + englishKeyWords
            # si appresta ad attendere un punto o una parola chiave         
            # msg, inputType, default, keyWords, valori nulli non ammessi
            self.waitFor(prompt, \
                         QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS, \
                         None, \
                         keyWords, QadInputModeEnum.NOT_NULL)
            self.isValidPreviousInput = False # per gestire il comando anche in macro
            return False
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA "Specificare angolo inscritto: " (da step = 5)
      elif self.step == 6: # 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
            ctrlPressed = self.getPointMapTool().ctrlKey
         else: # il punto arriva come parametro della funzione
            value = msg
            ctrlPressed = False

         if type(value) == QgsPoint:
            self.angle = qad_utils.getAngleBy2Pts(self.centerPt, value)             
         else:
            self.angle = value

         arc = QadArc()         
         if arc.fromStartCenterPtsAngle(self.startPt, self.centerPt, self.angle) == True:
            if ctrlPressed: # cambio direzione
               arc.inverse()
               
            self.plugIn.setLastPoint(arc.getEndPt())
            points = arc.asPolyline()
            if points is not None:
               # se i punti sono così vicini da essere considerati uguali
               if qad_utils.ptNear(self.startPt, arc.getStartPt()):
                  self.plugIn.setLastSegmentAng(arc.getTanDirectionOnEndPt())
               else:
                  self.plugIn.setLastSegmentAng(arc.getTanDirectionOnStartPt() + math.pi)

               self.getPointMapTool().setPolarAngOffset(self.plugIn.lastSegmentAng)
               
               qad_layer.addLineToLayer(self.plugIn, currLayer, points)               
               return True # fine comando

         # si appresta ad attendere un punto o un numero reale         
         # msg, inputType, default, keyWords, valori nulli non ammessi
         self.waitFor(QadMsg.translate("Command_ARC", "Specify the included angle (hold Ctrl to switch direction): "), \
                      QadInputTypeEnum.POINT2D | QadInputTypeEnum.ANGLE, \
                      None, "", \
                      QadInputModeEnum.NOT_NULL | QadInputModeEnum.NOT_ZERO)
         self.isValidPreviousInput = False # per gestire il comando anche in macro         
         return False

      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA "Specificare lunghezza della corda: " (da step = 5)
      elif self.step == 7: # 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
            ctrlPressed = self.getPointMapTool().ctrlKey
         else: # il punto arriva come parametro della funzione
            value = msg
            ctrlPressed = False

         if type(value) == QgsPoint:
            self.chord = qad_utils.getDistance(self.startPt, value)             
         else:
            self.chord = value

         arc = QadArc()         
         if arc.fromStartCenterPtsChord(self.startPt, self.centerPt, self.chord) == True:
            if ctrlPressed: # cambio direzione
               arc.inverse()

            self.plugIn.setLastPoint(arc.getEndPt())
            points = arc.asPolyline()
            if points is not None:
               # se i punti sono così vicini da essere considerati uguali
               if qad_utils.ptNear(self.startPt, arc.getStartPt()):
                  self.plugIn.setLastSegmentAng(arc.getTanDirectionOnEndPt())
               else:
                  self.plugIn.setLastSegmentAng(arc.getTanDirectionOnStartPt() + math.pi)

               self.getPointMapTool().setPolarAngOffset(self.plugIn.lastSegmentAng)
               
               qad_layer.addLineToLayer(self.plugIn, currLayer, points)               
               return True # fine comando

         # si appresta ad attendere un punto o un numero reale         
         # msg, inputType, default, keyWords, valori positivi ammessi
         self.waitFor(QadMsg.translate("Command_ARC", "Specify the chord length (hold Ctrl to switch direction): "), \
                      QadInputTypeEnum.POINT2D | QadInputTypeEnum.FLOAT, \
                      None, "", \
                      QadInputModeEnum.NOT_NULL | QadInputModeEnum.NOT_ZERO | QadInputModeEnum.NOT_NEGATIVE)
         self.isValidPreviousInput = False # per gestire il comando anche in macro         
         return False
                 
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA "Specificare punto finale dell'arco: " (da step = 1)
      elif self.step == 8: # 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
                  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.endPt = value
         self.plugIn.setLastPoint(self.endPt)

         # imposto il map tool
         self.getPointMapTool().arcEndPt = self.endPt
         self.getPointMapTool().setMode(Qad_arc_maptool_ModeEnum.START_END_PT_KNOWN_ASK_FOR_CENTER)
      
         keyWords = QadMsg.translate("Command_ARC", "Angle") + "/" + \
                    QadMsg.translate("Command_ARC", "Direction") + "/" + \
                    QadMsg.translate("Command_ARC", "Radius")
                    
         prompt = QadMsg.translate("Command_ARC", "Specify the center point of the arc (hold Ctrl to switch direction) or [{0}]: ").format(keyWords)

         englishKeyWords = "Angle" + "/" + "Direction" + "/" + "Radius"
         keyWords += "_" + englishKeyWords
         # si appresta ad attendere un punto o una parola chiave         
         # msg, inputType, default, keyWords, valori nulli non ammessi
         self.waitFor(prompt, \
                      QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS, \
                      None, \
                      keyWords, QadInputModeEnum.NOT_NULL)
         
         self.step = 9
         return False
         
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA "Specificare centro dell'arco o [Angolo/Direzione/Raggio]: " (da step = 8)
      elif self.step == 9: # dopo aver atteso un punto 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
                  return True # fine comando
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False

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

         if type(value) == unicode:
            if value == QadMsg.translate("Command_ARC", "Angle") or value == "Angle":
               # imposto il map tool
               self.getPointMapTool().setMode(Qad_arc_maptool_ModeEnum.START_END_PT_KNOWN_ASK_FOR_ANGLE)
               # si appresta ad attendere un punto o un numero reale         
               # msg, inputType, default, keyWords, isNullable
               self.waitFor(QadMsg.translate("Command_ARC", "Specify the included angle (hold Ctrl to switch direction): "), \
                            QadInputTypeEnum.POINT2D | QadInputTypeEnum.ANGLE, \
                            None, "", QadInputModeEnum.NOT_NULL | QadInputModeEnum.NOT_ZERO)
               self.step = 10
               return False                              
            elif value == QadMsg.translate("Command_ARC", "Direction") or value == "Direction":
               # imposto il map tool
               self.getPointMapTool().setMode(Qad_arc_maptool_ModeEnum.START_END_PT_KNOWN_ASK_FOR_TAN)
               # si appresta ad attendere un punto o un numero reale         
               # msg, inputType, default, keyWords, isNullable
               self.waitFor(QadMsg.translate("Command_ARC", "Specify the tangent direction for the start point of the arc (hold Ctrl to switch direction): "), \
                            QadInputTypeEnum.POINT2D | QadInputTypeEnum.ANGLE, \
                            None, "", QadInputModeEnum.NOT_NULL)
               self.step = 11
               return False            
            elif value == QadMsg.translate("Command_ARC", "Radius") or value == "Radius":
               # imposto il map tool
               self.getPointMapTool().setMode(Qad_arc_maptool_ModeEnum.START_END_PT_KNOWN_ASK_FOR_RADIUS)
               # si appresta ad attendere un punto o un numero reale         
               # msg, inputType, default, keyWords, isNullable
               self.waitFor(QadMsg.translate("Command_ARC", "Specify the radius of the arc (hold Ctrl to switch direction): "), \
                            QadInputTypeEnum.POINT2D | QadInputTypeEnum.FLOAT, \
                            None, "", \
                            QadInputModeEnum.NOT_NULL | QadInputModeEnum.NOT_ZERO | QadInputModeEnum.NOT_NEGATIVE)
               self.step = 12
               return False                              
         elif type(value) == QgsPoint: # se é stato inserito il centro dell'arco
            self.centerPt = value

            arc = QadArc()         
            if arc.fromStartCenterEndPts(self.startPt, self.centerPt, self.endPt) == True:
               if ctrlPressed: # cambio direzione
                  arc.inverse()
                  
               self.plugIn.setLastPoint(arc.getEndPt())
               points = arc.asPolyline()
               if points is not None:
                  # se i punti sono così vicini da essere considerati uguali
                  if qad_utils.ptNear(self.startPt, arc.getStartPt()):
                     self.plugIn.setLastSegmentAng(arc.getTanDirectionOnEndPt())
                  else:
                     self.plugIn.setLastSegmentAng(arc.getTanDirectionOnStartPt() + math.pi)

                  self.getPointMapTool().setPolarAngOffset(self.plugIn.lastSegmentAng)
                  
                  qad_layer.addLineToLayer(self.plugIn, currLayer, points)               
                  return True # fine comando
            
            keyWords = QadMsg.translate("Command_ARC", "Angle") + "/" + \
                       QadMsg.translate("Command_ARC", "Direction") + "/" + \
                       QadMsg.translate("Command_ARC", "Radius")
                       
            prompt = QadMsg.translate("Command_ARC", "Specify the center point of the arc (hold Ctrl to switch direction) or [{0}]: ").format(keyWords)
                      
            englishKeyWords = "Angle" + "/" + "Direction" + "/" + "Radius"
            keyWords += "_" + englishKeyWords
            # si appresta ad attendere un punto o una parola chiave         
            # msg, inputType, default, keyWords, isNullable
            self.waitFor(prompt, \
                         QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS, \
                         None, \
                         keyWords, QadInputModeEnum.NOT_NULL)
            self.isValidPreviousInput = False # per gestire il comando anche in macro                     
            return False
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA "Specificare angolo inscritto: " (da step = 9)
      elif self.step == 10: # 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
            ctrlPressed = self.getPointMapTool().ctrlKey
         else: # il punto arriva come parametro della funzione
            value = msg
            ctrlPressed = False

         if type(value) == QgsPoint:
            self.angle = qad_utils.getAngleBy2Pts(self.startPt, value)
         else:
            self.angle = value
            
         arc = QadArc()         
         if arc.fromStartEndPtsAngle(self.startPt, self.endPt, self.angle) == True:
            if ctrlPressed: # cambio direzione
               arc.inverse()
               
            self.plugIn.setLastPoint(arc.getEndPt())
            points = arc.asPolyline()
            if points is not None:
               # se i punti sono così vicini da essere considerati uguali
               if qad_utils.ptNear(self.startPt, arc.getStartPt()):
                  self.plugIn.setLastSegmentAng(arc.getTanDirectionOnEndPt())
               else:
                  self.plugIn.setLastSegmentAng(arc.getTanDirectionOnStartPt() + math.pi)

               self.getPointMapTool().setPolarAngOffset(self.plugIn.lastSegmentAng)
               
               qad_layer.addLineToLayer(self.plugIn, currLayer, points)               
               return True # fine comando

         # si appresta ad attendere un punto o un numero reale         
         # msg, inputType, default, keyWords, valori non nulli
         self.waitFor(QadMsg.translate("Command_ARC", "Specify the included angle (hold Ctrl to switch direction): "), \
                      QadInputTypeEnum.POINT2D | QadInputTypeEnum.ANGLE, \
                      None, "", \
                      QadInputModeEnum.NOT_NULL | QadInputModeEnum.NOT_ZERO)
         self.isValidPreviousInput = False # per gestire il comando anche in macro         
         return False
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA "Specificare direzione tangente per il punto iniziale dell'arco: " (da step = 9)
      elif self.step == 11: # 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
            ctrlPressed = self.getPointMapTool().ctrlKey
         else: # il punto arriva come parametro della funzione
            value = msg
            ctrlPressed = False
            
         if type(value) == QgsPoint:
            self.angleTan = qad_utils.getAngleBy2Pts(self.startPt, value)             
         else:
            self.angleTan = value

         arc = QadArc()         
         if arc.fromStartEndPtsTan(self.startPt, self.endPt, self.angleTan) == True:
            if ctrlPressed: # cambio direzione
               arc.inverse()
               
            self.plugIn.setLastPoint(arc.getEndPt())
            points = arc.asPolyline()
            if points is not None:
               # se i punti sono così vicini da essere considerati uguali
               if qad_utils.ptNear(self.startPt, arc.getStartPt()):
                  self.plugIn.setLastSegmentAng(arc.getTanDirectionOnEndPt())
               else:
                  self.plugIn.setLastSegmentAng(arc.getTanDirectionOnStartPt() + math.pi)

               self.getPointMapTool().setPolarAngOffset(self.plugIn.lastSegmentAng)
               
               qad_layer.addLineToLayer(self.plugIn, currLayer, points)               
               return True # fine comando

         # si appresta ad attendere un punto o un numero reale         
         # msg, inputType, default, keyWords, isNullable
         self.waitFor(QadMsg.translate("Command_ARC", "Specify the tangent direction for the start point of the arc (hold Ctrl to switch direction): "), \
                      QadInputTypeEnum.POINT2D | QadInputTypeEnum.ANGLE, \
                      None, "", QadInputModeEnum.NOT_NULL)
         self.isValidPreviousInput = False # per gestire il comando anche in macro
         return False


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA "Specificare raggio dell'arco: " (da step = 9)
      elif self.step == 12: # 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
            ctrlPressed = self.getPointMapTool().ctrlKey
         else: # il punto arriva come parametro della funzione
            value = msg
            ctrlPressed = False

         if type(value) == QgsPoint:
            self.radius = qad_utils.getDistance(self.endPt, value)             
         else:
            self.radius = value

         self.plugIn.setLastRadius(self.radius)
         
         arc = QadArc()
         if arc.fromStartEndPtsRadius(self.startPt, self.endPt, self.radius) == True:
            if ctrlPressed: # cambio direzione
               arc.inverse()
               
            self.plugIn.setLastPoint(arc.getEndPt())
            points = arc.asPolyline()
            if points is not None:
               # se i punti sono così vicini da essere considerati uguali
               if qad_utils.ptNear(self.startPt, arc.getStartPt()):
                  self.plugIn.setLastSegmentAng(arc.getTanDirectionOnEndPt())
               else:
                  self.plugIn.setLastSegmentAng(arc.getTanDirectionOnStartPt() + math.pi)

               self.getPointMapTool().setPolarAngOffset(self.plugIn.lastSegmentAng)
               
               qad_layer.addLineToLayer(self.plugIn, currLayer, points)               
               return True # fine comando

         # si appresta ad attendere un punto o un numero reale         
         # msg, inputType, default, keyWords, valori positivi
         self.waitFor(QadMsg.translate("Command_ARC", "Specify the radius of the arc (hold Ctrl to switch direction): "), \
                      QadInputTypeEnum.POINT2D | QadInputTypeEnum.FLOAT, \
                      None, "", \
                      QadInputModeEnum.NOT_NULL | QadInputModeEnum.NOT_ZERO | QadInputModeEnum.NOT_NEGATIVE)
         self.isValidPreviousInput = False # per gestire il comando anche in macro
         return False


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA CENTRO DELL'ARCO (da step = 1)
      elif self.step == 13: # 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
                  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.centerPt = value
         self.plugIn.setLastPoint(value)

         # imposto il map tool
         self.getPointMapTool().arcCenterPt = self.centerPt
         self.getPointMapTool().setMode(Qad_arc_maptool_ModeEnum.CENTER_PT_KNOWN_ASK_FOR_START_PT)

         # si appresta ad attendere un punto
         self.waitForPoint(QadMsg.translate("Command_ARC", "Specify the start point of the arc: "))
         self.step = 14
         
         return False


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA PUNTO INIZIALE DELL'ARCO (da step = 13)
      elif self.step == 14: # 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
                  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.startPt = value
         self.plugIn.setLastPoint(value)

         # imposto il map tool
         self.getPointMapTool().arcStartPt = self.startPt
         self.getPointMapTool().setMode(Qad_arc_maptool_ModeEnum.START_CENTER_PT_KNOWN_ASK_FOR_END_PT)
         
         keyWords = QadMsg.translate("Command_ARC", "Angle") + "/" + \
                    QadMsg.translate("Command_ARC", "chord Length")
         
         prompt = QadMsg.translate("Command_ARC", "Specify the final point of the arc (hold Ctrl to switch direction) or [{0}]: ").format(keyWords)
                           
         englishKeyWords = "Angle" + "/" + "chord Length"
         keyWords += "_" + englishKeyWords
         # si appresta ad attendere un punto o una parola chiave         
         # msg, inputType, default, keyWords, isNullable
         self.waitFor(prompt, \
                      QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS, \
                      None, \
                      keyWords, QadInputModeEnum.NOT_NULL)
         
         self.step = 5
         return False class QadCIRCLECommandClass(QadCommandClass):
   
   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadCIRCLECommandClass(self.plugIn)
   
   def getName(self):
      return QadMsg.translate("Command_list", "CIRCLE")

   def getEnglishName(self):
      return "CIRCLE"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runCIRCLECommand)

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/circle.png")

   def getNote(self):
      # impostare le note esplicative del comando
      return QadMsg.translate("Command_CIRCLE", "Draws a circlerc by many methods.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      # se questo flag = True il comando serve all'interno di un altro comando per disegnare un cerchio
      # che non verrà salvato su un layer
      self.virtualCmd = False
      self.rubberBandBorderColor = None
      self.rubberBandFillColor = None
      self.centerPt = None
      self.radius = None
      self.area = 100      

   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      if (self.plugIn is not None):
         if self.PointMapTool is None:
            self.PointMapTool = Qad_circle_maptool(self.plugIn)
            self.PointMapTool.setRubberBandColor(self.rubberBandBorderColor, self.rubberBandFillColor)
         return self.PointMapTool
      else:
         return None
   
   def setRubberBandColor(self, rubberBandBorderColor, rubberBandFillColor):
      self.rubberBandBorderColor = rubberBandBorderColor
      self.rubberBandFillColor = rubberBandFillColor
      if self.PointMapTool is not None:
         self.PointMapTool.setRubberBandColor(self.rubberBandBorderColor, self.rubberBandFillColor)
         
   def run(self, msgMapTool = False, msg = None):
      self.isValidPreviousInput = True # per gestire il comando anche in macro

      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

      currLayer = None
      if self.virtualCmd == False: # se si vuole veramente salvare il cerchio in un layer   
         # il layer corrente deve essere editabile e di tipo linea o poligono
         currLayer, errMsg = qad_layer.getCurrLayerEditable(self.plugIn.canvas, [QGis.Line, QGis.Polygon])
         if currLayer is None:
            self.showErr(errMsg)
            return True # fine comando
         self.getPointMapTool().geomType = QGis.Line if currLayer.geometryType() == QGis.Line else QGis.Polygon                                   

      #=========================================================================
      # RICHIESTA PRIMO PUNTO o CENTRO
      if self.step == 0: # inizio del comando
         # imposto il map tool
         self.getPointMapTool().setMode(Qad_circle_maptool_ModeEnum.NONE_KNOWN_ASK_FOR_CENTER_PT)        
         keyWords = QadMsg.translate("Command_CIRCLE", "3Points") + "/" + \
                    QadMsg.translate("Command_CIRCLE", "2POints") + "/" + \
                    QadMsg.translate("Command_CIRCLE", "Ttr (tangent tangent radius)")
         prompt = QadMsg.translate("Command_CIRCLE", "Specify the center point of the circle or [{0}]: ").format(keyWords)

         englishKeyWords = "3Points" + "/" + "2POints" + "/" + "Ttr (tangent tangent radius)"
         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
         return False

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA CENTRO
      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
                  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 value is None:
            if self.plugIn.lastPoint is not None:
               value = self.plugIn.lastPoint
            else:
               return True # fine comando

         if type(value) == unicode:
            if value == QadMsg.translate("Command_CIRCLE", "3Points") or value == "3Points":
               # imposto il map tool
               self.getPointMapTool().setMode(Qad_circle_maptool_ModeEnum.NONE_KNOWN_ASK_FOR_FIRST_PT)
               # si appresta ad attendere un punto
               self.waitForPoint(QadMsg.translate("Command_CIRCLE", "Specify first point on the circle: "))
               self.step = 4           
            elif value == QadMsg.translate("Command_CIRCLE", "2POints") or value == "2POints":
               # imposto il map tool
               self.getPointMapTool().setMode(Qad_circle_maptool_ModeEnum.NONE_KNOWN_ASK_FOR_FIRST_DIAM_PT)
               # si appresta ad attendere un punto
               self.waitForPoint(QadMsg.translate("Command_CIRCLE", "Specify first end of the circle diameter: "))
               self.step = 7     
            elif value == QadMsg.translate("Command_CIRCLE", "Ttr (tangent tangent radius)") or \
                 value == "Ttr (tangent tangent radius)":
               # imposto il map tool
               self.getPointMapTool().setMode(Qad_circle_maptool_ModeEnum.NONE_KNOWN_ASK_FOR_FIRST_TAN)
               # si appresta ad attendere un punto
               self.waitForPoint(QadMsg.translate("Command_CIRCLE", "Specify first tangent element of the circle: "))
               self.step = 9     
         elif type(value) == QgsPoint: # se é stato inserito il centro del cerchio           
            self.centerPt = value
            self.plugIn.setLastPoint(value)
            
            # imposto il map tool
            self.getPointMapTool().centerPt = self.centerPt
            self.getPointMapTool().setMode(Qad_circle_maptool_ModeEnum.CENTER_PT_KNOWN_ASK_FOR_RADIUS)                                
           
            keyWords = QadMsg.translate("Command_CIRCLE", "Diameter") + "/" + \
                       QadMsg.translate("Command_CIRCLE", "Area")
            prompt = QadMsg.translate("Command_CIRCLE", "Specify the circle radius or [{0}]: ").format(keyWords)
            
            englishKeyWords = "Diameter" + "/" + "Area"
            keyWords += "_" + englishKeyWords
            # si appresta ad attendere un punto 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 = 2
         
         return False

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA RAGGIO O DIAMETRO O AREA
      elif self.step == 2: # dopo aver atteso un punto 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
                  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) == unicode:
            if value == QadMsg.translate("Command_CIRCLE", "Diameter") or value == "Diameter":
               # imposto il map tool
               self.getPointMapTool().setMode(Qad_circle_maptool_ModeEnum.CENTER_PT_KNOWN_ASK_FOR_DIAM)
               # si appresta ad attendere un punto o un numero reale   
               # msg, inputType, default, keyWords, valori positivi
               self.waitFor(QadMsg.translate("Command_CIRCLE", "Specify the circle diameter: "), \
                            QadInputTypeEnum.POINT2D | QadInputTypeEnum.FLOAT, \
                            None, \
                            "", \
                            QadInputModeEnum.NOT_NULL | QadInputModeEnum.NOT_ZERO | QadInputModeEnum.NOT_NEGATIVE)
               self.step = 3           
            elif value == QadMsg.translate("Command_CIRCLE", "Area") or value == "Area":
               msg = QadMsg.translate("Command_CIRCLE", "Enter circle area in current unit <{0}>: ")
               # si appresta ad attendere un numero reale         
               # msg, inputType, default, keyWords, valori positivi
               self.waitFor(msg.format(str(self.area)), QadInputTypeEnum.FLOAT, \
                            self.area, "", \
                            QadInputModeEnum.NOT_NULL | QadInputModeEnum.NOT_ZERO | QadInputModeEnum.NOT_NEGATIVE)
               self.getPointMapTool().setMode(Qad_circle_maptool_ModeEnum.NONE_KNOWN_ASK_FOR_CENTER_PT)
               self.step = 13         
         elif type(value) == QgsPoint or type(value) == float: # se é stato inserito il raggio del cerchio            
            if type(value) == QgsPoint: # se é stato inserito il raggio del cerchio con un punto                        
               self.radius = qad_utils.getDistance(self.centerPt, value)
            else:
               self.radius = value
               
            self.plugIn.setLastRadius(self.radius)     

            circle = QadCircle()
            circle.set(self.centerPt, self.radius)
            points = circle.asPolyline()
            if points is not None:
               if self.virtualCmd == False: # se si vuole veramente salvare il cerchio in un layer
                  if currLayer.geometryType() == QGis.Line:
                     qad_layer.addLineToLayer(self.plugIn, currLayer, points)
                  else:
                     qad_layer.addPolygonToLayer(self.plugIn, currLayer, points)               
               return True # fine comando
            
            keyWords = QadMsg.translate("Command_CIRCLE", "Diameter") + "/" + \
                       QadMsg.translate("Command_CIRCLE", "Area")
            prompt = QadMsg.translate("Command_CIRCLE", "Specify the circle radius or [{0}]: ").format(keyWords)
                                 
            englishKeyWords = "Diameter" + "/" + "Area"
            keyWords += "_" + englishKeyWords
            # si appresta ad attendere un punto o una parola chiave         
            # msg, inputType, default, keyWords, valori positivi
            self.waitFor(prompt, \
                         QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS, \
                         None, \
                         keyWords, QadInputModeEnum.NOT_ZERO | QadInputModeEnum.NOT_NEGATIVE)
            self.isValidPreviousInput = False # per gestire il comando anche in macro                       
         return False

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DIAMETRO DEL CERCHIO (da step = 2)
      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) == QgsPoint: # se é stato inserito un punto          
            self.radius = qad_utils.getDistance(self.centerPt, value) / 2
         elif type(value) == float: # se é stato inserito un numero reale
            self.radius = value

         self.plugIn.setLastRadius(self.radius)     
      
         circle = QadCircle()         
         circle.set(self.centerPt, self.radius)
         points = circle.asPolyline()
         if points is not None:
            if self.virtualCmd == False: # se si vuole veramente salvare il cerchio in un layer   
               if currLayer.geometryType() == QGis.Line:
                  qad_layer.addLineToLayer(self.plugIn, currLayer, points)
               else:
                  qad_layer.addPolygonToLayer(self.plugIn, currLayer, points)               
            return True # fine comando
      
         # si appresta ad attendere un punto o un numero reale   
         # msg, inputType, default, keyWords, valori positivi
         self.waitFor(QadMsg.translate("Command_CIRCLE", "Specify the circle diameter: "), \
                      QadInputTypeEnum.POINT2D | QadInputTypeEnum.FLOAT, \
                      None, \
                      "", \
                      QadInputModeEnum.NOT_NULL | QadInputModeEnum.NOT_ZERO | QadInputModeEnum.NOT_NEGATIVE)
         self.isValidPreviousInput = False # per gestire il comando anche in macro     
         return False
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL PRIMO PUNTO DEL CERCHIO (da step = 1)
      elif self.step == 4: # 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
                  return True # fine comando
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False
               
            snapTypeOnSel = self.getPointMapTool().snapTypeOnSelection
            value = self.getPointMapTool().point
            entity = self.getPointMapTool().entity
         else: # il punto arriva come parametro della funzione
            value = msg
            snapTypeOnSel = QadSnapTypeEnum.NONE

         # se é stato selezionato un punto con la modalità TAN_DEF é un punto differito
         if snapTypeOnSel == QadSnapTypeEnum.TAN_DEF and entity.isInitialized():
            self.firstPt = None
            self.firstPtTan = value
            self.firstGeomTan = QgsGeometry(entity.getGeometry()) # duplico la geometria         
            coordTransform = QgsCoordinateTransform(entity.layer.crs(), self.plugIn.canvas.mapSettings().destinationCrs()) # trasformo la geometria
            self.firstGeomTan.transform(coordTransform)         
            # imposto il map tool
            self.getPointMapTool().setMode(Qad_circle_maptool_ModeEnum.FIRST_PT_KNOWN_ASK_FOR_SECOND_PT)
         else: # altrimenti é un punto esplicito 
            self.firstPt = value
            self.plugIn.setLastPoint(value)    
            # imposto il map tool
            self.getPointMapTool().firstPt = self.firstPt
            self.getPointMapTool().setMode(Qad_circle_maptool_ModeEnum.FIRST_PT_KNOWN_ASK_FOR_SECOND_PT)
   
         # si appresta ad attendere un punto         
         self.waitForPoint(QadMsg.translate("Command_CIRCLE", "Specify second point on the circle: "))
         
         self.step = 5
         return False
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL SECONDO PUNTO DEL CERCHIO (da step = 4)
      elif self.step == 5:  # 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
                  return True # fine comando
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False

            snapTypeOnSel = self.getPointMapTool().snapTypeOnSelection
            value = self.getPointMapTool().point
            entity = self.getPointMapTool().entity
         else: # il punto arriva come parametro della funzione
            value = msg
            snapTypeOnSel = QadSnapTypeEnum.NONE

         # se é stato selezionato un punto con la modalità TAN_DEF é un punto differito
         if snapTypeOnSel == QadSnapTypeEnum.TAN_DEF and entity.isInitialized():
            self.secondPt = None
            self.secondPtTan = value
            self.secondGeomTan = QgsGeometry(entity.getGeometry()) # duplico la geometria         
            coordTransform = QgsCoordinateTransform(entity.layer.crs(), self.plugIn.canvas.mapSettings().destinationCrs()) # trasformo la geometria
            self.secondGeomTan.transform(coordTransform)         
            # imposto il map tool
            self.getPointMapTool().setMode(Qad_circle_maptool_ModeEnum.FIRST_SECOND_PT_KNOWN_ASK_FOR_THIRD_PT)
         else: # altrimenti é un punto esplicito 
            self.secondPt = value
            self.plugIn.setLastPoint(value)    
            # imposto il map tool
            self.getPointMapTool().secondPt = self.secondPt
            self.getPointMapTool().setMode(Qad_circle_maptool_ModeEnum.FIRST_SECOND_PT_KNOWN_ASK_FOR_THIRD_PT)
   
         # si appresta ad attendere un punto
         self.waitForPoint(QadMsg.translate("Command_CIRCLE", "Specify the third point on the circle: "))
         
         self.step = 6
         return False
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL TERZO PUNTO DEL CERCHIO (da step = 5)
      elif self.step == 6:  # 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
                  return True # fine comando
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False

            snapTypeOnSel = self.getPointMapTool().snapTypeOnSelection
            value = self.getPointMapTool().point
            entity = self.getPointMapTool().entity
         else: # il punto arriva come parametro della funzione
            value = msg
            snapTypeOnSel = QadSnapTypeEnum.NONE

         # se é stato selezionato un punto con la modalità TAN_DEF é un punto differito
         if snapTypeOnSel == QadSnapTypeEnum.TAN_DEF and entity.isInitialized():
            self.thirdPt = None
            self.thirdPtTan = value
            self.thirdGeomTan = QgsGeometry(entity.getGeometry()) # duplico la geometria         
            coordTransform = QgsCoordinateTransform(entity.layer.crs(), self.plugIn.canvas.mapSettings().destinationCrs()) # trasformo la geometria
            self.thirdGeomTan.transform(coordTransform)         
         else: # altrimenti é un punto esplicito 
            self.thirdPt = value
            self.plugIn.setLastPoint(value)    

         circle = QadCircle()                  
         points = None
         if self.firstPt is None: # se il primo punto é definito con un punto differito
            if self.secondPt is None: # se il secondo punto é definito con un punto differito
               if self.thirdPt is None: # se il terzo punto é definito con un punto differito
                  if circle.from3TanPts(self.firstGeomTan, self.firstPtTan, \
                                        self.secondGeomTan, self.secondPtTan, \
                                        self.thirdGeomTan, self.thirdPtTan) == True:
                     points = circle.asPolyline()
               else: # se il terzo punto é definito con un punto esplicito
                  if circle.from1IntPt2TanPts(self.thirdPt, self.firstGeomTan, self.firstPtTan,
                                              self.secondGeomTan, self.secondPtTan) == True:
                     points = circle.asPolyline()
            else: # se il secondo punto é definito con un punto esplicito
               if self.thirdPt is None: # se il terzo punto é definito con un punto differito
                  if circle.from1IntPt2TanPts(self.secondPt, self.firstGeomTan, self.firstPtTan,
                                              self.thirdGeomTan, self.thirdPtTan) == True:
                     points = circle.asPolyline()
               else: # se il terzo punto é definito con un punto esplicito
                  if circle.from2IntPts1TanPt(self.secondPt, self.thirdPt, \
                                              self.firstGeomTan, self.firstPtTan) == True:
                     points = circle.asPolyline()
         else: # se il primo punto é definito con un punto esplicito
            if self.secondPt is None: # se il secondo punto é definito con un punto differito
               if self.thirdPt is None: # se il terzo punto é definito con un punto differito
                  if circle.from1IntPt2TanPts(self.firstPt, self.secondGeomTan, self.secondPtTan,
                                              self.thirdGeomTan, self.thirdPtTan) == True:
                     points = circle.asPolyline()
               else: # se il terzo punto é definito con un punto esplicito
                  if circle.from2IntPts1TanPt(self.firstPt, self.thirdPt, \
                                              self.secondGeomTan, self.secondPtTan) == True:
                     points = circle.asPolyline()
            else: # se il secondo punto é definito con un punto esplicito
               if self.thirdPt is None: # se il terzo punto é definito con un punto differito
                  if circle.from2IntPts1TanPt(self.firstPt, self.secondPt, \
                                              self.thirdGeomTan, self.thirdPtTan) == True:
                     points = circle.asPolyline()
               else: # se il terzo punto é definito con un punto esplicito
                  if circle.from3Pts(self.firstPt, self.secondPt, value) == True:
                     points = circle.asPolyline()
                     
         if points is not None:
            self.centerPt = circle.center
            self.radius = circle.radius           
            if self.virtualCmd == False: # se si vuole veramente salvare il cerchio in un layer   
               if currLayer.geometryType() == QGis.Line:
                  qad_layer.addLineToLayer(self.plugIn, currLayer, points)
               else:
                  qad_layer.addPolygonToLayer(self.plugIn, currLayer, points)               
            return True # fine comando
         
         # si appresta ad attendere un punto
         self.waitForPoint(QadMsg.translate("Command_CIRCLE", "Specify the third point on the circle: "))
         self.isValidPreviousInput = False # per gestire il comando anche in macro     
         return False

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DELLA PRIMA ESTREMITA' DIAM DEL CERCHIO (da step = 1)
      elif self.step == 7:  # 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
                  return True # fine comando
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False

            snapTypeOnSel = self.getPointMapTool().snapTypeOnSelection
            value = self.getPointMapTool().point
            entity = self.getPointMapTool().entity
         else: # il punto arriva come parametro della funzione
            value = msg
            snapTypeOnSel = QadSnapTypeEnum.NONE

         # se é stato selezionato un punto con la modalità TAN_DEF é un punto differito
         if snapTypeOnSel == QadSnapTypeEnum.TAN_DEF and entity.isInitialized():
            self.firstDiamPt = None
            self.firstDiamPtTan = value
            self.firstDiamGeomTan = QgsGeometry(entity.getGeometry()) # duplico la geometria         
            coordTransform = QgsCoordinateTransform(entity.layer.crs(), self.plugIn.canvas.mapSettings().destinationCrs()) # trasformo la geometria
            self.firstDiamGeomTan.transform(coordTransform)         
            # imposto il map tool
            self.getPointMapTool().setMode(Qad_circle_maptool_ModeEnum.FIRST_DIAM_PT_KNOWN_ASK_FOR_SECOND_DIAM_PT)
         else: # altrimenti é un punto esplicito 
            self.firstDiamPt = value        
            # imposto il map tool
            self.getPointMapTool().firstDiamPt = self.firstDiamPt
            self.getPointMapTool().setMode(Qad_circle_maptool_ModeEnum.FIRST_DIAM_PT_KNOWN_ASK_FOR_SECOND_DIAM_PT)
   
         # si appresta ad attendere un punto         
         self.waitForPoint(QadMsg.translate("Command_CIRCLE", "Specify second end of the circle diameter: "))
         
         self.step = 8
         return False

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DELLA SECONDA ESTREMITA' DIAM DEL CERCHIO (da step = 7)
      elif self.step == 8:  # 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
                  return True # fine comando
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False

            snapTypeOnSel = self.getPointMapTool().snapTypeOnSelection
            value = self.getPointMapTool().point
            entity = self.getPointMapTool().entity
         else: # il punto arriva come parametro della funzione
            value = msg
            snapTypeOnSel = QadSnapTypeEnum.NONE

         # se é stato selezionato un punto con la modalità TAN_DEF é un punto differito
         if snapTypeOnSel == QadSnapTypeEnum.TAN_DEF and entity.isInitialized():
            self.secondDiamPt = None
            self.secondDiamPtTan = value
            self.secondDiamGeomTan = QgsGeometry(entity.getGeometry()) # duplico la geometria
            coordTransform = QgsCoordinateTransform(entity.layer.crs(), self.plugIn.canvas.mapSettings().destinationCrs()) # trasformo la geometria
            self.secondDiamGeomTan.transform(coordTransform)            
         else: # altrimenti é un punto esplicito 
            self.secondDiamPt = value  
         
         circle = QadCircle()                  
         points = None
         if self.firstDiamPt is None: # se il diametro é definito con il primo punto differito
            if self.secondDiamPt is None: # il diametro é definito con il secondo punto differito
               if circle.fromDiamEnds2TanPts(self.firstDiamGeomTan, self.firstDiamPtTan, \
                                             self.secondDiamGeomTan, self.secondDiamPtTan) == True:
                  points = circle.asPolyline()
            else: # se il diametro è definito con il secondo punto esplicito
               if circle.fromDiamEndsPtTanPt(self.secondDiamPt, self.firstDiamGeomTan, self.firstDiamPtTan) == True:
                  points = circle.asPolyline()
         else: # se il diametro è definito con il primo punto esplicito
            if self.secondDiamPt is None: # il diametro è definito con il secondo punto differito
               if circle.fromDiamEndsPtTanPt(self.firstDiamPt, self.secondDiamGeomTan, self.secondDiamPtTan) == True:
                  points = circle.asPolyline()
            else: # se il diametro è definito con il secondo punto esplicito
               if circle.fromDiamEnds(self.firstDiamPt, self.secondDiamPt) == True:
                  points = circle.asPolyline()
                  
         if points is not None:
            self.centerPt = circle.center
            self.radius = circle.radius
            if self.virtualCmd == False: # se si vuole veramente salvare il cerchio in un layer   
               if currLayer.geometryType() == QGis.Line:
                  qad_layer.addLineToLayer(self.plugIn, currLayer, points)
               else:
                  qad_layer.addPolygonToLayer(self.plugIn, currLayer, points)             
            return True # fine comand         
         
         # si appresta ad attendere un punto
         self.waitForPoint(QadMsg.translate("Command_CIRCLE", "Specify second end of the circle diameter: "))
         self.isValidPreviousInput = False # per gestire il comando anche in macro     
         return False

                 
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA PRIMA TANGENTE (da step = 1)
      elif self.step == 9: # 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
                  return True # fine comando
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False

            entity = self.getPointMapTool().entity
         else: # il punto arriva come parametro della funzione
            # si appresta ad attendere un punto
            self.waitForPoint(QadMsg.translate("Command_CIRCLE", "Specify first tangent element of the circle: "))
            self.isValidPreviousInput = False # per gestire il comando anche in macro     
            return False

         if not entity.isInitialized(): # se non è stata selezionata una entità
            # si appresta ad attendere un punto
            self.waitForPoint(QadMsg.translate("Command_CIRCLE", "Specify first tangent element of the circle: "))
            self.isValidPreviousInput = False # per gestire il comando anche in macro     
            return False
         
         wkbType = entity.getGeometry().wkbType()
         if wkbType == QGis.WKBPoint or wkbType == QGis.WKBMultiPoint:     
            self.showErr(QadMsg.translate("Command_CIRCLE", "\nSelect a circle, an arc or a line."))
            # si appresta ad attendere un punto
            self.waitForPoint(QadMsg.translate("Command_CIRCLE", "Specify first tangent element of the circle: "))
            self.isValidPreviousInput = False # per gestire il comando anche in macro
            return False
         
         self.tanGeom1 = QgsGeometry(entity.getGeometry())         
         coordTransform = QgsCoordinateTransform(entity.layer.crs(), self.plugIn.canvas.mapSettings().destinationCrs()) # trasformo la geometria
         self.tanGeom1.transform(coordTransform)         
         self.tanPt1 = self.getPointMapTool().point

         # imposto il map tool
         self.getPointMapTool().tanGeom1 = self.tanGeom1
         self.getPointMapTool().tanPt1 = self.tanPt1
         self.getPointMapTool().setMode(Qad_circle_maptool_ModeEnum.FIRST_TAN_KNOWN_ASK_FOR_SECOND_TAN)
      
         # si appresta ad attendere un punto         
         self.waitForPoint(QadMsg.translate("Command_CIRCLE", "Specify second tangent element of the circle: "))
         self.step = 10
         return False
         
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA SECONDA TANGENTE (da step = 9)
      elif self.step == 10: # 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
                  return True # fine comando
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False

            entity = self.getPointMapTool().entity
         else: # il punto arriva come parametro della funzione
            # si appresta ad attendere un punto
            self.waitForPoint(QadMsg.translate("Command_CIRCLE", "Specify second tangent element of the circle: "))
            self.isValidPreviousInput = False # per gestire il comando anche in macro
            return False

         if not entity.isInitialized(): # se non è stata selezionata una entità
            # si appresta ad attendere un punto
            self.waitForPoint(QadMsg.translate("Command_CIRCLE", "Specify second tangent element of the circle: "))
            self.isValidPreviousInput = False # per gestire il comando anche in macro
            return False

         wkbType = entity.getGeometry().wkbType()
         if wkbType == QGis.WKBPoint or wkbType == QGis.WKBMultiPoint:     
            self.showErr(QadMsg.translate("Command_CIRCLE", "\nSelect a circle, an arc or a line."))
            # si appresta ad attendere un punto
            self.waitForPoint(QadMsg.translate("Command_CIRCLE", "Specify second tangent element of the circle: "))
            self.isValidPreviousInput = False # per gestire il comando anche in macro
            return False
         
         self.tanGeom2 = QgsGeometry(entity.getGeometry())
         coordTransform = QgsCoordinateTransform(entity.layer.crs(), self.plugIn.canvas.mapSettings().destinationCrs()) # trasformo la geometria
         self.tanGeom2.transform(coordTransform)                  
         self.tanPt2 = self.getPointMapTool().point

         # imposto il map tool
         self.getPointMapTool().tanGeom2 = self.tanGeom2
         self.getPointMapTool().tanPt2 = self.tanPt2
         self.getPointMapTool().setMode(Qad_circle_maptool_ModeEnum.FIRST_SECOND_TAN_KNOWN_ASK_FOR_RADIUS)
      
         # si appresta ad attendere un punto o un numero reale         
         # msg, inputType, default, keyWords, valori positivi
         msg = QadMsg.translate("Command_CIRCLE", "Specify the circle radius <{0}>: ")
         self.waitFor(msg.format(str(self.plugIn.lastRadius)), \
                      QadInputTypeEnum.POINT2D | QadInputTypeEnum.FLOAT, \
                      self.plugIn.lastRadius, "", \
                      QadInputModeEnum.NOT_ZERO | QadInputModeEnum.NOT_NEGATIVE)
         self.step = 11
         return False
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA RAGGIO (da step = 10)
      elif self.step == 11: # 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:
            self.startPtForRadius = value
            
            # imposto il map tool
            self.getPointMapTool().startPtForRadius = self.startPtForRadius
            self.getPointMapTool().setMode(Qad_circle_maptool_ModeEnum.FIRST_SECOND_TAN_FIRSTPTRADIUS_KNOWN_ASK_FOR_SECONDPTRADIUS)
         
            # si appresta ad attendere un punto
            self.waitForPoint(QadMsg.translate("Command_CIRCLE", "Specify second point: "))
            self.step = 12
            return False            
         else:
            self.plugIn.setLastRadius(value)

            circle = QadCircle()
            if circle.from2TanPtsRadius(self.tanGeom1, self.tanPt1, \
                                        self.tanGeom2, self.tanPt2, value) == True:
               points = circle.asPolyline()
               if points is not None:
                  self.centerPt = circle.center
                  self.radius = circle.radius
                  if self.virtualCmd == False: # se si vuole veramente salvare il cerchio in un layer   
                     if currLayer.geometryType() == QGis.Line:
                        qad_layer.addLineToLayer(self.plugIn, currLayer, points)
                     else:
                        qad_layer.addPolygonToLayer(self.plugIn, currLayer, points)               
               else:
                  self.showMsg(QadMsg.translate("Command_CIRCLE", "\nThe circle doesn't exist."))
            else:
               self.showMsg(QadMsg.translate("Command_CIRCLE", "\nThe circle doesn't exist."))
                  
            return True # fine comando

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA SECONDO PUNTO DEL RAGGIO (da step = 11)
      elif self.step == 12: # 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
                  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.radius = qad_utils.getDistance(self.startPtForRadius, value)
         self.plugIn.setLastRadius(self.radius)     

         circle = QadCircle()                  
         if circle.from2TanPtsRadius(self.tanGeom1, self.tanPt1, \
                                     self.tanGeom2, self.tanPt2, self.radius) == True:
            points = circle.asPolyline()
            if points is not None:
               self.centerPt = circle.center
               self.radius = circle.radius
               if self.virtualCmd == False: # se si vuole veramente salvare il cerchio in un layer   
                  if currLayer.geometryType() == QGis.Line:
                     qad_layer.addLineToLayer(self.plugIn, currLayer, points)
                  else:
                     qad_layer.addPolygonToLayer(self.plugIn, currLayer, points)               
            else:
               self.showMsg(QadMsg.translate("Command_CIRCLE", "\nThe circle doesn't exist."))
         else:
            self.showMsg(QadMsg.translate("Command_CIRCLE", "\nThe circle doesn't exist."))
         return True # fine comando

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA AREA DEL CERCHIO (da step = 2)
      elif self.step == 13: # dopo aver atteso un numero 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 NON usato il tasto destro del mouse
                  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: # è stata inserita l'area
            self.area = value
      
            circle = QadCircle()         
            circle.fromCenterArea(self.centerPt, self.area)
            self.radius = circle.radius 
            self.plugIn.setLastRadius(self.radius)     
            points = circle.asPolyline()
            if points is not None:
               if self.virtualCmd == False: # se si vuole veramente salvare il cerchio in un layer   
                  if currLayer.geometryType() == QGis.Line:
                     qad_layer.addLineToLayer(self.plugIn, currLayer, points)
                  else:
                     qad_layer.addPolygonToLayer(self.plugIn, currLayer, points)               
               return True # fine comando

         self.isValidPreviousInput = False # per gestire il comando anche in macro      
         return False class QadDSETTINGSCommandClass(QadCommandClass):
   
   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadDSETTINGSCommandClass(self.plugIn)
   
   def getName(self):
      return QadMsg.translate("Command_list", "DSETTINGS")

   def getEnglishName(self):
      return "DSETTINGS"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runDSETTINGSCommand)

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/dsettings.png")

   def getNote(self):
      # impostare le note esplicative del comando
      return QadMsg.translate("Command_DSETTINGS", "Drafting Settings (snaps, etc.).")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
            
   def run(self, msgMapTool = False, msg = None):
      Form = QadDSETTINGSDialog(self.plugIn)
      Form.exec_()
      return True class QadLINECommandClass(QadCommandClass):

   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadLINECommandClass(self.plugIn)
   
   def getName(self):
      return QadMsg.translate("Command_list", "LINE")

   def getEnglishName(self):
      return "LINE"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runLINECommand)

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/line.png")

   def getNote(self):
      # impostare le note esplicative del comando
      return QadMsg.translate("Command_LINE", "Creates straight line segments.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      self.vertices = []
      self.rubberBand = createRubberBand(self.plugIn.canvas, QGis.Line)
      self.firstPtTan = None
      self.firstPtPer = None      
      # 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.virtualCmd = False

   def __del__(self):
      QadCommandClass.__del__(self)
      self.rubberBand.hide()
      self.plugIn.canvas.scene().removeItem(self.rubberBand)


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


   def addVertex(self, point):
      self.vertices.append(point)     
      self.addPointToRubberBand(point)            
      self.plugIn.setLastPointAndSegmentAng(self.vertices[-1])            
      self.setTmpGeometriesToMapTool()
      
   def delLastVertex(self):
      if len(self.vertices) > 0:
         del self.vertices[-1] # cancello ultimo vertice
         self.removeLastPointToRubberBand()
         if len(self.vertices) > 0:
            self.plugIn.setLastPointAndSegmentAng(self.vertices[-1])
         self.setTmpGeometriesToMapTool()      
         

   #============================================================================
   # addPointToRubberBand
   #============================================================================
   def addPointToRubberBand(self, point, doUpdate = True):
      numberOfVertices = self.rubberBand.numberOfVertices()
         
      if numberOfVertices == 2:
         # per un baco non ancora capito: se la linea ha solo 2 vertici e 
         # hanno la stessa x o y (linea orizzontale o verticale) 
         # la linea non viene disegnata perciò sposto un pochino la x o la y                 
         adjustedPoint = qad_utils.getAdjustedRubberBandVertex(self.rubberBand.getPoint(0, 0), point)                                                               
         self.rubberBand.addPoint(adjustedPoint, doUpdate)
      else:
         self.rubberBand.addPoint(point, doUpdate)
      
      
   #============================================================================
   # removeLastPointToRubberBand
   #============================================================================
   def removeLastPointToRubberBand(self):
      self.rubberBand.removeLastPoint()

   def addLinesToLayer(self, layer):
      i = 1
      while i < len(self.vertices):                     
         qad_layer.addLineToLayer(self.plugIn, layer,
                                  [self.vertices[i - 1], self.vertices[i]])
         i = i + 1


   #============================================================================
   # setTmpGeometriesToMapTool
   #============================================================================
   def setTmpGeometriesToMapTool(self):
      self.getPointMapTool().clearTmpGeometries()
      i = 1
      while i < len(self.vertices):                     
         # per lo snap aggiungo questa geometria temporanea
         self.getPointMapTool().appendTmpGeometry(QgsGeometry.fromPolyline([self.vertices[i - 1], self.vertices[i]]))
         i = i + 1

            
   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

      if self.virtualCmd == False: # se si vuole veramente salvare la polylinea in un layer   
         currLayer, errMsg = qad_layer.getCurrLayerEditable(self.plugIn.canvas, QGis.Line)
         if currLayer is None:
            self.showErr(errMsg)
            return True # fine comando
      
      # RICHIESTA PRIMO PUNTO 
      if self.step == 0: # inizio del comando
         # imposto il map tool
         self.getPointMapTool().setMode(Qad_line_maptool_ModeEnum.NONE_KNOWN_ASK_FOR_FIRST_PT)
         # si appresta ad attendere un punto o enter
         #                        msg, inputType,              default, keyWords, nessun controllo         
         self.waitFor(QadMsg.translate("Command_LINE", "Specify first point: "), \
                      QadInputTypeEnum.POINT2D, None, "", QadInputModeEnum.NONE)
         self.step = 1
         return False
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA PUNTO OPPURE MENU PRINCIPALE
      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
               if self.getPointMapTool().rightButton == True: # se usato il tasto destro del mouse
                  if self.virtualCmd == False: # se si vuole veramente salvare in un layer   
                     self.addLinesToLayer(currLayer)
                  return True # fine comando
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False

            snapTypeOnSel = self.getPointMapTool().snapTypeOnSelection
            value = self.getPointMapTool().point
            entity = self.getPointMapTool().entity
         else: # il punto arriva come parametro della funzione
            value = msg
            snapTypeOnSel = QadSnapTypeEnum.NONE

         if type(value) == unicode:
            if value == QadMsg.translate("Command_LINE", "Undo") or value == "Undo":               
               self.delLastVertex() # cancello ultimo vertice
               # imposto il map tool
               if len(self.vertices) == 0:
                  self.getPointMapTool().setMode(Qad_line_maptool_ModeEnum.NONE_KNOWN_ASK_FOR_FIRST_PT)
                  # si appresta ad attendere un punto o enter
                  #                        msg, inputType,              default, keyWords, nessun controllo
                  self.waitFor(QadMsg.translate("Command_LINE", "Specify first point: "), \
                               QadInputTypeEnum.POINT2D, None, "", QadInputModeEnum.NONE)
                  return False                  
               else:
                  self.getPointMapTool().firstPt = self.vertices[-1]
                  self.getPointMapTool().setMode(Qad_line_maptool_ModeEnum.FIRST_PT_KNOWN_ASK_FOR_SECOND_PT)        
            elif value == QadMsg.translate("Command_LINE", "Close") or value == "Close":
               newPt = self.vertices[0]
               self.addVertex(newPt) # aggiungo un nuovo vertice
               if self.virtualCmd == False: # se si vuole veramente salvare in un layer   
                  self.addLinesToLayer(currLayer)
               return True # fine comando
         else:
            if len(self.vertices) == 0: # primo punto
               if value is None:
                  if self.plugIn.lastPoint is not None:
                     value = self.plugIn.lastPoint
                  else:
                     return True # fine comando
   
               # se é stato selezionato un punto con la modalità TAN_DEF é un punto differito
               if snapTypeOnSel == QadSnapTypeEnum.TAN_DEF and entity.isInitialized():
                  # se era stato selezionato un punto esplicito
                  if (self.firstPtTan is None) and (self.firstPtPer is None):                     
                     self.firstPtPer = None
                     self.firstPtTan = value
                     self.firstGeom = QgsGeometry(entity.getGeometry()) # duplico la geometria         
                     coordTransform = QgsCoordinateTransform(entity.layer.crs(), self.plugIn.canvas.mapSettings().destinationCrs()) # trasformo la geometria
                     self.firstGeom.transform(coordTransform)
                     # imposto il map tool
                     self.getPointMapTool().tan1 = self.firstPtTan
                     self.getPointMapTool().geom1 = self.firstGeom
                     self.getPointMapTool().setMode(Qad_line_maptool_ModeEnum.FIRST_TAN_KNOWN_ASK_FOR_SECOND_PT)
                  # se era stato selezionato un punto con la modalità TAN_DEF   
                  elif self.firstPtTan is not None:
                     secondGeom = QgsGeometry(entity.getGeometry()) # duplico la geometria         
                     coordTransform = QgsCoordinateTransform(entity.layer.crs(), self.plugIn.canvas.mapSettings().destinationCrs()) # trasformo la geometria
                     secondGeom.transform(coordTransform)
                     tangent = qad_utils.lineFrom2TanPts(self.firstGeom, self.firstPtTan, secondGeom, value)
                     if tangent is not None:
                        # prendo il punto più vicino a value
                        if qad_utils.getDistance(tangent[0], value) < qad_utils.getDistance(tangent[1], value):                              
                           self.addVertex(tangent[1]) # aggiungo un nuovo vertice
                           self.addVertex(tangent[0]) # aggiungo un nuovo vertice
                           self.getPointMapTool().firstPt = tangent[0]
                        else:
                           self.addVertex(tangent[0]) # aggiungo un nuovo vertice
                           self.addVertex(tangent[1]) # aggiungo un nuovo vertice
                           self.getPointMapTool().firstPt = tangent[1]
                        # imposto il map tool
                        self.getPointMapTool().setMode(Qad_line_maptool_ModeEnum.FIRST_PT_KNOWN_ASK_FOR_SECOND_PT)         
                     else:
                        self.showMsg(QadMsg.translate("Command_LINE", "\nNo tangent possible"))
                  # se era stato selezionato un punto con la modalità PER_DEF              
                  elif self.firstPtPer is not None:
                     secondGeom = QgsGeometry(entity.getGeometry()) # duplico la geometria         
                     coordTransform = QgsCoordinateTransform(entity.layer.crs(), self.plugIn.canvas.mapSettings().destinationCrs()) # trasformo la geometria
                     secondGeom.transform(coordTransform)
                     tangent = qad_utils.lineFromTanPerPts(secondGeom, value, self.firstGeom, self.firstPtPer)
                     if tangent is not None:
                        # prendo il punto più vicino a value
                        if qad_utils.getDistance(tangent[0], value) < qad_utils.getDistance(tangent[1], value):                              
                           self.addVertex(tangent[1]) # aggiungo un nuovo vertice
                           self.addVertex(tangent[0]) # aggiungo un nuovo vertice
                           self.getPointMapTool().firstPt = tangent[0]
                        else:
                           self.addVertex(tangent[0]) # aggiungo un nuovo vertice
                           self.addVertex(tangent[1]) # aggiungo un nuovo vertice
                           self.getPointMapTool().firstPt = tangent[1]
                        # imposto il map tool
                        self.getPointMapTool().setMode(Qad_line_maptool_ModeEnum.FIRST_PT_KNOWN_ASK_FOR_SECOND_PT)         
                     else:
                        self.showMsg(QadMsg.translate("Command_LINE", "\nNo tangent possible"))                        
                        
               # se é stato selezionato un punto con la modalità PER_DEF é un punto differito
               elif snapTypeOnSel == QadSnapTypeEnum.PER_DEF and entity.isInitialized():
                  # se era stato selezionato un punto esplicito
                  if (self.firstPtTan is None) and (self.firstPtPer is None):
                     self.firstPtTan = None
                     self.firstPtPer = value
                     self.firstGeom = QgsGeometry(entity.getGeometry()) # duplico la geometria         
                     coordTransform = QgsCoordinateTransform(entity.layer.crs(), self.plugIn.canvas.mapSettings().destinationCrs()) # trasformo la geometria
                     self.firstGeom.transform(coordTransform)         
                     # imposto il map tool
                     self.getPointMapTool().per1 = self.firstPtPer
                     self.getPointMapTool().geom1 = self.firstGeom
                     self.getPointMapTool().setMode(Qad_line_maptool_ModeEnum.FIRST_PER_KNOWN_ASK_FOR_SECOND_PT)               
                  # se era stato selezionato un punto con la modalità TAN_DEF   
                  elif self.firstPtTan is not None:
                     secondGeom = QgsGeometry(entity.getGeometry()) # duplico la geometria         
                     coordTransform = QgsCoordinateTransform(entity.layer.crs(), self.plugIn.canvas.mapSettings().destinationCrs()) # trasformo la geometria
                     secondGeom.transform(coordTransform)
                     tangent = qad_utils.lineFromTanPerPts(self.firstGeom, self.firstPtTan, secondGeom, value)
                     if tangent is not None:
                        # prendo il punto più vicino a value
                        if qad_utils.getDistance(tangent[0], value) < qad_utils.getDistance(tangent[1], value):                              
                           self.addVertex(tangent[1]) # aggiungo un nuovo vertice
                           self.addVertex(tangent[0]) # aggiungo un nuovo vertice
                           self.getPointMapTool().firstPt = tangent[0]
                        else:
                           self.addVertex(tangent[0]) # aggiungo un nuovo vertice
                           self.addVertex(tangent[1]) # aggiungo un nuovo vertice
                           self.getPointMapTool().firstPt = tangent[1]
                        # imposto il map tool
                        self.getPointMapTool().setMode(Qad_line_maptool_ModeEnum.FIRST_PT_KNOWN_ASK_FOR_SECOND_PT)         
                     else:
                        self.showMsg(QadMsg.translate("Command_LINE", "\nNo perpendicular possible"))
                  # se era stato selezionato un punto con la modalità PER_DEF              
                  elif self.firstPtPer is not None:
                     secondGeom = QgsGeometry(entity.getGeometry()) # duplico la geometria         
                     coordTransform = QgsCoordinateTransform(entity.layer.crs(), self.plugIn.canvas.mapSettings().destinationCrs()) # trasformo la geometria
                     secondGeom.transform(coordTransform)
                     line = qad_utils.lineFrom2PerPts(self.firstGeom, self.firstPtPer, secondGeom, value)
                     if line is not None:
                        # prendo il punto più vicino a value
                        if qad_utils.getDistance(line[0], value) < qad_utils.getDistance(line[1], value):                              
                           self.addVertex(line[1]) # aggiungo un nuovo vertice
                           self.addVertex(line[0]) # aggiungo un nuovo vertice
                           self.getPointMapTool().firstPt = line[0]
                        else:
                           self.addVertex(line[0]) # aggiungo un nuovo vertice
                           self.addVertex(line[1]) # aggiungo un nuovo vertice
                           self.getPointMapTool().firstPt = line[1]
                        # imposto il map tool
                        self.getPointMapTool().setMode(Qad_line_maptool_ModeEnum.FIRST_PT_KNOWN_ASK_FOR_SECOND_PT)         
                     else:
                        self.showMsg(QadMsg.translate("Command_LINE", "\nNo perpendicular possible"))
               else: # altrimenti é un punto esplicito
                  # se era stato selezionato un punto con la modalità TAN_DEF
                  if self.firstPtTan is not None:
                     snapper = QadSnapper()
                     snapper.setSnapPointCRS(self.plugIn.canvas.mapSettings().destinationCrs())
                     snapper.setSnapType(QadSnapTypeEnum.TAN)
                     snapper.setStartPoint(value)
                     oSnapPoints = snapper.getSnapPoint(self.firstGeom, self.firstPtTan, 
                                                        self.plugIn.canvas.mapSettings().destinationCrs())
                     # memorizzo il punto di snap in point (prendo il primo valido)
                     for item in oSnapPoints.items():
                        points = item[1]
                        if points is not None:
                           self.addVertex(points[0]) # aggiungo un nuovo vertice
                           self.addVertex(value) # aggiungo un nuovo vertice
                           break

                     if len(self.vertices) == 0:
                        self.showMsg(QadMsg.translate("Command_LINE", "\nNo tangent possible"))                                          
                  # se era stato selezionato un punto con la modalità PER_DEF
                  elif self.firstPtPer is not None:
                     snapper = QadSnapper()
                     snapper.setSnapPointCRS(self.plugIn.canvas.mapSettings().destinationCrs())
                     snapper.setSnapType(QadSnapTypeEnum.PER)
                     snapper.setStartPoint(value)
                     oSnapPoints = snapper.getSnapPoint(self.firstGeom, self.firstPtPer, 
                                                        self.plugIn.canvas.mapSettings().destinationCrs())
                     # memorizzo il punto di snap in point (prendo il primo valido)
                     for item in oSnapPoints.items():
                        points = item[1]
                        if points is not None:
                           self.addVertex(points[0]) # aggiungo un nuovo vertice
                           self.addVertex(value) # aggiungo un nuovo vertice
                           break

                     if len(self.vertices) == 0:                        
                        self.showMsg(QadMsg.translate("Command_LINE", "\nNo perpendicular possible"))
                  else:
                     self.addVertex(value) # aggiungo un nuovo vertice

                  if len(self.vertices) > 0:                         
                     # imposto il map tool
                     self.getPointMapTool().firstPt = value
                     self.getPointMapTool().setMode(Qad_line_maptool_ModeEnum.FIRST_PT_KNOWN_ASK_FOR_SECOND_PT)         
            else: # secondo punto
               if value is None:
                  if self.virtualCmd == False: # se si vuole veramente salvare in un layer   
                     self.addLinesToLayer(currLayer)
                  return True # fine comando
               # se il primo punto é esplicito
               if len(self.vertices) > 0 is not None:
                  self.addVertex(value) # aggiungo un nuovo vertice    
                  # imposto il map tool
                  self.getPointMapTool().firstPt = value
                  self.getPointMapTool().setMode(Qad_line_maptool_ModeEnum.FIRST_PT_KNOWN_ASK_FOR_SECOND_PT)         

         if len(self.vertices) > 2:
            keyWords = QadMsg.translate("Command_LINE", "Close") + "/" + \
                       QadMsg.translate("Command_LINE", "Undo")
         else:
            keyWords = QadMsg.translate("Command_LINE", "Undo")
         prompt = QadMsg.translate("Command_LINE", "Specify next point or [{0}]: ").format(keyWords)
            
         englishKeyWords = "Close" + "/" + "Undo"
         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 False class QadERASECommandClass(QadCommandClass):

   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadERASECommandClass(self.plugIn)
   
   def getName(self):
      return QadMsg.translate("Command_list", "ERASE")

   def getEnglishName(self):
      return "ERASE"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runERASECommand)

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/erase.png")

   def getNote(self):
      # impostare le note esplicative del comando
      return QadMsg.translate("Command_ERASE", "Removes objects of the map.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      self.SSGetClass = QadSSGetClass(plugIn)
      self.SSGetClass.onlyEditableLayers = True

   def __del__(self):
      QadCommandClass.__del__(self)
      del self.SSGetClass
      
   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      if self.step == 0: # quando si é in fase di selezione entità
         return self.SSGetClass.getPointMapTool(drawMode)
      else:
         return QadCommandClass.getPointMapTool(self, drawMode)

   def run(self, msgMapTool = False, msg = None):
            
      #=========================================================================
      # RICHIESTA PRIMO PUNTO PER SELEZIONE OGGETTI
      if self.step == 0: # inizio del comando
         if self.SSGetClass.run(msgMapTool, msg) == True:
            # selezione terminata
            self.step = 1
            return self.run(msgMapTool, msg)
         else:
            return False
      
      #=========================================================================
      # CANCELLAZIONE OGGETTI
      elif self.step == 1:
         self.plugIn.beginEditCommand("Feature deleted", self.SSGetClass.entitySet.getLayerList())
              
         for layerEntitySet in self.SSGetClass.entitySet.layerEntitySetList:
            # plugIn, layer, featureIds, refresh
            if qad_layer.deleteFeaturesToLayer(self.plugIn, layerEntitySet.layer, \
                                               layerEntitySet.featureIds, False) == False:
               self.plugIn.destroyEditCommand()
               return
            
         self.plugIn.endEditCommand()
            
         return True # fine comando class QadMPOLYGONCommandClass(QadCommandClass):

   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadMPOLYGONCommandClass(self.plugIn)
   
   def getName(self):
      return QadMsg.translate("Command_list", "MPOLYGON")

   def getEnglishName(self):
      return "MPOLYGON"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runMPOLYGONCommand)

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/mpolygon.png")

   def getNote(self):
      # impostare le note esplicative del comando      
      return QadMsg.translate("Command_MPOLYGON", "Draws a polygon by many methods.\nA Polygon is a closed sequence of straight line segments,\narcs or a combination of two.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      self.vertices = []
      # se questo flag = True il comando serve all'interno di un altro comando per disegnare un poligono
      # che non verrà salvato su un layer
      self.virtualCmd = False
      self.rubberBandBorderColor = None
      self.rubberBandFillColor = None
      self.PLINECommand = None

   def __del__(self):
      QadCommandClass.__del__(self)
      if self.PLINECommand is not None:
         del self.PLINECommand


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


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


   def setRubberBandColor(self, rubberBandBorderColor, rubberBandFillColor):
      self.rubberBandBorderColor = rubberBandBorderColor
      self.rubberBandFillColor = rubberBandFillColor
      if self.PLINECommand is not None:
         self.PLINECommand.setRubberBandColor(rubberBandBorderColor, rubberBandFillColor)


   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

      if self.virtualCmd == False: # se si vuole veramente salvare la polylinea in un layer   
         currLayer, errMsg = qad_layer.getCurrLayerEditable(self.plugIn.canvas, QGis.Polygon)
         if currLayer is None:
            self.showErr(errMsg)
            return True # fine comando

      #=========================================================================
      # RICHIESTA PRIMO PUNTO PER SELEZIONE OGGETTI
      if self.step == 0:
         self.PLINECommand = QadPLINECommandClass(self.plugIn, True)
         self.PLINECommand.setRubberBandColor(self.rubberBandBorderColor, self.rubberBandFillColor)
         # 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.asToolForMPolygon = True # per rubberband tipo poligono
         self.PLINECommand.run(msgMapTool, msg)
         self.step = 1
         return False # continua     

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA PUNTO (da step = 0 o 1)
      elif self.step == 1: # dopo aver atteso un punto si riavvia il comando
         if self.PLINECommand.run(msgMapTool, msg) == True:
            verticesLen = len(self.PLINECommand.vertices)
            if verticesLen >= 3:
               self.vertices = self.PLINECommand.vertices[:] # copio la lista
               firstVertex = self.vertices[0]
               # se l'ultimo vertice non é uguale al primo
               if self.vertices[verticesLen - 1] != firstVertex:
                  # aggiungo un vertice con le stesse coordinate del primo
                  self.vertices.append(firstVertex)
               if self.virtualCmd == False: # se si vuole veramente salvare la polylinea in un layer   
                  if qad_layer.addPolygonToLayer(self.plugIn, currLayer, self.vertices) == False:                     
                     self.showMsg(QadMsg.translate("Command_MPOLYGON", "\nPolygon not valid.\n"))
                     del self.vertices[:] # svuoto la lista
            else:
               self.showMsg(QadMsg.translate("Command_MPOLYGON", "\nPolygon not valid.\n"))
                               
            del self.PLINECommand
            self.PLINECommand = None
         
            return True # fine
            
         return False class QadMBUFFERCommandClass(QadCommandClass):
   
   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadMBUFFERCommandClass(self.plugIn)
   
   def getName(self):
      return QadMsg.translate("Command_list", "MBUFFER")

   def getEnglishName(self):
      return "MBUFFER"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runMBUFFERCommand)

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/mbuffer.png")

   def getNote(self):
      # impostare le note esplicative del comando
      return QadMsg.translate("Command_MBUFFER", "Creates polygons by buffering selected objects.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      # se questo flag = True il comando serve all'interno di un altro comando per disegnare un buffer
      # che non verrà salvato su un layer
      self.virtualCmd = False
      self.rubberBandBorderColor = None
      self.rubberBandFillColor = None      
      self.SSGetClass = QadSSGetClass(plugIn)
      self.entitySet = QadEntitySet()
      self.width = 0
      self.segments = self.plugIn.segments # il numero di segmenti per l'approssimazione delle curve

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


   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      if self.step == 0: # quando si é in fase di selezione entità
         return self.SSGetClass.getPointMapTool()
      else:
         if (self.plugIn is not None):
            if self.PointMapTool is None:
               self.PointMapTool = Qad_mbuffer_maptool(self.plugIn)
               self.PointMapTool.setRubberBandColor(self.rubberBandBorderColor, self.rubberBandFillColor)
            return self.PointMapTool
         else:
            return None


   def getCurrentContextualMenu(self):
      if self.step == 0: # quando si é in fase di selezione entità
         return self.SSGetClass.getCurrentContextualMenu()
      else:
         return self.contextualMenu

   
   def setRubberBandColor(self, rubberBandBorderColor, rubberBandFillColor):
      self.rubberBandBorderColor = rubberBandBorderColor
      self.rubberBandFillColor = rubberBandFillColor
      if self.PointMapTool is not None:
         self.PointMapTool.setRubberBandColor(self.rubberBandBorderColor, self.rubberBandFillColor)


   def AddGeoms(self, currLayer):
      bufferGeoms = []
      tolerance = QadVariables.get(QadMsg.translate("Environment variables", "TOLERANCE2APPROXCURVE"))
            
      for layerEntitySet in self.entitySet.layerEntitySetList:
         layer = layerEntitySet.layer
         geoms = layerEntitySet.getGeometryCollection()
         
         for geom in geoms:
            # trasformo la geometria nel crs del canvas per lavorare con coordinate piane xy
            newGeom = self.layerToMapCoordinates(layer, geom)
            g = qad_utils.ApproxCurvesOnGeom(newGeom.buffer(self.width, self.segments), \
                                             self.segments, self.segments, \
                                             tolerance)
            # trasformo la geometria nel crs del layer
            bufferGeoms.append(self.mapToLayerCoordinates(layer, g))

      self.plugIn.beginEditCommand("Feature buffered", currLayer)
      
      # filtro le features per tipo
      pointGeoms, lineGeoms, polygonGeoms = qad_utils.filterGeomsByType(bufferGeoms, \
                                                                        currLayer.geometryType())
      # aggiungo le geometrie del tipo corretto
      if currLayer.geometryType() == QGis.Line:
         polygonToLines = []
         # Riduco le geometrie in linee
         for g in polygonGeoms:
            lines = qad_utils.asPointOrPolyline(g)
            for l in lines:
               if l.type() == QGis.Line:
                   polygonToLines.append(l)
         # plugIn, layer, geoms, coordTransform , refresh, check_validity
         if qad_layer.addGeomsToLayer(self.plugIn, currLayer, polygonToLines, None, False, False) == False:
            self.plugIn.destroyEditCommand()
            return
            
         del polygonGeoms[:] # svuoto la lista

      # plugIn, layer, geoms, coordTransform , refresh, check_validity
      if qad_layer.addGeomsToLayer(self.plugIn, currLayer, bufferGeoms, None, False, False) == False:  
         self.plugIn.destroyEditCommand()
         return

      if pointGeoms is not None and len(pointGeoms) > 0:
         PointTempLayer = qad_layer.createQADTempLayer(self.plugIn, QGis.Point)
         self.plugIn.addLayerToLastEditCommand("Feature buffered", PointTempLayer)
      
      if lineGeoms is not None and len(lineGeoms) > 0:
         LineTempLayer = qad_layer.createQADTempLayer(self.plugIn, QGis.Line)
         self.plugIn.addLayerToLastEditCommand("Feature buffered", LineTempLayer)
         
      if polygonGeoms is not None and len(polygonGeoms) > 0:
         PolygonTempLayer = qad_layer.createQADTempLayer(self.plugIn, QGis.Polygon)
         self.plugIn.addLayerToLastEditCommand("Feature buffered", PolygonTempLayer)

      # aggiungo gli scarti nei layer temporanei di QAD
      # trasformo la geometria in quella dei layer temporanei 
      # plugIn, pointGeoms, lineGeoms, polygonGeoms, coord, refresh
      if qad_layer.addGeometriesToQADTempLayers(self.plugIn, pointGeoms, lineGeoms, polygonGeoms, \
                                                None, False) == False:
         self.plugIn.destroyEditCommand()
         return

      self.plugIn.endEditCommand()


   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

      currLayer = None
      if self.virtualCmd == False: # se si vuole veramente salvare la polylinea in un layer   
         # il layer corrente deve essere editabile e di tipo linea o poligono
         currLayer, errMsg = qad_layer.getCurrLayerEditable(self.plugIn.canvas, [QGis.Line, QGis.Polygon])
         if currLayer is None:
            self.showErr(errMsg)
            return True # fine comando
         
         # il layer corrente non deve appartenere a quotature
         dimStyleList = QadDimStyles.getDimListByLayer(currLayer)
         if len(dimStyleList) > 0:
            dimStyleNames = ""
            for i in xrange(0, len(dimStyleList), 1):
               if i > 0:
                  dimStyleNames += ", "
               dimStyleNames += dimStyleList[i].name
            errMsg = QadMsg.translate("QAD", "\nCurrent layer is a layer referenced to {0} dimension style and it is not valid.\n")                        
            self.showErr(errMsg.format(dimStyleNames))
            return True # fine comando
            
      #=========================================================================
      # RICHIESTA SELEZIONE OGGETTI
      if self.step == 0: # inizio del comando
         if self.SSGetClass.run(msgMapTool, msg) == True:
            # selezione terminata
            self.step = 1
            self.getPointMapTool().refreshSnapType() # aggiorno lo snapType che può  essere variato dal maptool di selezione entità                     
            return self.run(msgMapTool, msg)
      
      #=========================================================================
      # BUFFER OGGETTI
      elif self.step == 1:
         self.entitySet.set(self.SSGetClass.entitySet)
         
         if self.entitySet.count() == 0:
            return True # fine comando

         # imposto il map tool
         self.getPointMapTool().setMode(Qad_mbuffer_maptool_ModeEnum.NONE_KNOWN_ASK_FOR_FIRST_PT)
         if currLayer is not None:
            self.getPointMapTool().geomType = QGis.Line if currLayer.geometryType() == QGis.Line else QGis.Polygon                          
        
         # si appresta ad attendere un punto o un numero reale         
         # msg, inputType, default, keyWords, valori positivi
         msg = QadMsg.translate("Command_MBUFFER", "Specify the buffer length <{0}>: ")
         self.waitFor(msg.format(str(self.plugIn.lastRadius)), \
                      QadInputTypeEnum.POINT2D | QadInputTypeEnum.FLOAT, \
                      self.plugIn.lastRadius, "", \
                      QadInputModeEnum.NOT_NULL | QadInputModeEnum.NOT_ZERO | QadInputModeEnum.NOT_NEGATIVE)
                  
         self.step = 2     
         return False
         
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA LARGHEZZA (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

         if type(value) == QgsPoint:
            self.startPtForBufferWidth = value
            
            # imposto il map tool
            self.getPointMapTool().startPtForBufferWidth = self.startPtForBufferWidth
            self.getPointMapTool().entitySet.set(self.entitySet)
            self.getPointMapTool().segments = self.segments
            self.getPointMapTool().setMode(Qad_mbuffer_maptool_ModeEnum.FIRST_PT_ASK_FOR_BUFFER_WIDTH)
         
            # si appresta ad attendere un punto
            self.waitForPoint(QadMsg.translate("Command_MBUFFER", "Specify second point: "))
            self.step = 3
            return False            
         else:
            self.width = value
            self.plugIn.setLastRadius(self.width)

            if self.virtualCmd == False: # se si vuole veramente salvare i buffer in un layer
               self.AddGeoms(currLayer)           

            return True # fine comando

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA SECONDO PUNTO DELLA LARGHEZZA BUFFER (da step = 2)
      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
                  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.width = qad_utils.getDistance(self.startPtForBufferWidth, value)
         self.plugIn.setLastRadius(self.width)     

         if self.virtualCmd == False: # se si vuole veramente salvare i buffer in un layer
            self.AddGeoms(currLayer)               

         return True # fine comando class QadROTATECommandClass(QadCommandClass):

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

   def getName(self):
      return QadMsg.translate("Command_list", "ROTATE")

   def getEnglishName(self):
      return "ROTATE"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runROTATECommand)

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/rotate.png")

   def getNote(self):
      # impostare le note esplicative del comando      
      return QadMsg.translate("Command_ROTATE", "Rotates objects around a base point.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      self.SSGetClass = QadSSGetClass(plugIn)
      self.SSGetClass.onlyEditableLayers = True
      self.entitySet = QadEntitySet()
      self.basePt = None
      self.copyFeatures = False
      self.Pt1ReferenceAng = None
      self.ReferenceAng = 0
      self.Pt1NewAng = None

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


   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      if self.step == 0: # quando si é in fase di selezione entità
         return self.SSGetClass.getPointMapTool()
      else:
         if (self.plugIn is not None):
            if self.PointMapTool is None:
               self.PointMapTool = Qad_rotate_maptool(self.plugIn)
            return self.PointMapTool
         else:
            return None


   def getCurrentContextualMenu(self):
      if self.step == 0: # quando si é in fase di selezione entità
         return self.SSGetClass.getCurrentContextualMenu()
      else:
         return self.contextualMenu


   #============================================================================
   # rotate
   #============================================================================
   def rotate(self, f, basePt, angle, rotFldName, layerEntitySet, entitySet):
      # verifico se l'entità appartiene ad uno stile di quotatura
      dimEntity = QadDimStyles.getDimEntity(layerEntitySet.layer, f.id())
      
      if dimEntity is None:
         # ruoto la feature e la rimuovo da entitySet (é la prima)
         f.setGeometry(qad_utils.rotateQgsGeometry(f.geometry(), 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.copyFeatures == False:
            # plugIn, layer, feature, refresh, check_validity
            if qad_layer.updateFeatureToLayer(self.plugIn, layerEntitySet.layer, f, False, False) == False:
               self.plugIn.destroyEditCommand()
               return False
         else:             
            # plugIn, layer, features, coordTransform, refresh, check_validity
            if qad_layer.addFeatureToLayer(self.plugIn, layerEntitySet.layer, f, None, False, False) == False:
               self.plugIn.destroyEditCommand()
               return False
         del layerEntitySet.featureIds[0]
      else:
         # ruoto la quota e la rimuovo da entitySet
         dimEntitySet = dimEntity.getEntitySet()
         if self.copyFeatures == False:
            if dimEntity.deleteToLayers(self.plugIn) == False:
               return False                      
         newDimEntity = QadDimEntity(dimEntity) # la copio
         newDimEntity.rotate(basePt, angle)
         if newDimEntity.addToLayers(self.plugIn) == False:
            return False             
         entitySet.subtract(dimEntitySet)
            
      return True


   def RotateGeoms(self, angle):      
      # copio entitySet
      entitySet = QadEntitySet(self.entitySet)
      
      self.plugIn.beginEditCommand("Feature rotated", entitySet.getLayerList())
      
      for layerEntitySet in 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):
            rotFldName = qad_layer.get_symbolRotationFieldName(layer)
                     
         while len(layerEntitySet.featureIds) > 0:
            featureId = layerEntitySet.featureIds[0]
            f = layerEntitySet.getFeature(featureId)

            if self.rotate(f, transformedBasePt, angle, rotFldName, layerEntitySet, entitySet) == False:  
               self.plugIn.destroyEditCommand()
               return

      self.plugIn.endEditCommand()


   def waitForRotation(self):
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_rotate_maptool_ModeEnum.BASE_PT_KNOWN_ASK_FOR_ROTATION_PT)

      keyWords = QadMsg.translate("Command_ROTATE", "Copy") + "/" + \
                 QadMsg.translate("Command_ROTATE", "Reference")
      prompt = QadMsg.translate("Command_ROTATE", "Specify rotation angle or [{0}] <{1}>: ").format(keyWords, \
               str(qad_utils.toDegrees(self.plugIn.lastRot)))
      
      englishKeyWords = "Copy" + "/" + "Reference"
      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, \
                   self.plugIn.lastRot, \
                   keyWords, QadInputModeEnum.NONE)      
      self.step = 3      


   def waitForReferenceRot(self):
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_rotate_maptool_ModeEnum.ASK_FOR_FIRST_PT_REFERENCE_ANG)
      
      msg = QadMsg.translate("Command_ROTATE", "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 = 4


   def waitForNewReferenceRot(self):
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_rotate_maptool_ModeEnum.BASE_PT_KNOWN_ASK_FOR_NEW_ROTATION_PT)
      
      keyWords = QadMsg.translate("Command_ROTATE", "Points")
      if self.plugIn.lastNewReferenceRot == 0:
         angle = self.plugIn.lastRot
      else:
         angle = self.plugIn.lastNewReferenceRot         
      prompt = QadMsg.translate("Command_ROTATE", "Specify new angle or [{0}] <{1}>: ").format(keyWords, str(qad_utils.toDegrees(angle)))                        
         
      englishKeyWords = "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.FLOAT | QadInputTypeEnum.KEYWORDS, \
                   angle, \
                   keyWords)
      self.step = 6
   

   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.SSGetClass.run(msgMapTool, msg) == True:
            # selezione terminata
            self.step = 1
            self.getPointMapTool().refreshSnapType() # aggiorno lo snapType che può essere variato dal maptool di selezione entità                    
            return self.run(msgMapTool, msg)
      
      #=========================================================================
      # RUOTA OGGETTI
      elif self.step == 1:
         self.entitySet.set(self.SSGetClass.entitySet)
         
         if self.entitySet.count() == 0:
            return True # fine comando

         # 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_ROTATE", "Specify base point: "))
                  
         self.step = 2     
         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
         self.getPointMapTool().entitySet.set(self.entitySet)
         # si appresta ad attendere l'angolo di rotazione                      
         self.waitForRotation()
         
         return False 
         
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA SECONDO PUNTO PER ANGOLO ROTAZIONE (da step = 2)
      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) == unicode:
            if value == QadMsg.translate("Command_ROTATE", "Copy") or value == "Copy":
               self.copyFeatures = True
               self.showMsg(QadMsg.translate("Command_ROTATE", "\nRotation of a copy of the selected objects."))
               # si appresta ad attendere l'angolo di rotazione               
               self.waitForRotation()                
            elif value == QadMsg.translate("Command_ROTATE", "Reference") or value == "Reference":
               # si appresta ad attendere l'angolo di riferimento                      
               self.waitForReferenceRot()
         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)
            self.plugIn.setLastRot(angle)

            self.RotateGeoms(angle)
            return True # fine comando
         
         return False

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA PRIMO PUNTO PER ANGOLO ROTAZIONE DI RIFERIMENTO (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) == float: # se é stato inserito l'angolo di rotazione
            self.ReferenceAng = qad_utils.toRadians(value)
            self.getPointMapTool().ReferenceAng = self.ReferenceAng 
            # si appresta ad attendere il nuovo angolo                    
            self.waitForNewReferenceRot()

         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_ROTATE", "Specify second point: "))
            self.step = 5           
            
         return False

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA SECONDO PUNTO PER ANGOLO ROTAZIONE DI RIFERIMENTO (da step = 4)
      elif self.step == 5: # 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

         angle = qad_utils.getAngleBy2Pts(self.Pt1ReferenceAng, value)
         self.ReferenceAng = angle
         self.getPointMapTool().ReferenceAng = self.ReferenceAng 
         # si appresta ad attendere il nuovo angolo                    
         self.waitForNewReferenceRot()
            
         return False

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA SECONDO PUNTO PER NUOVO ANGOLO ROTAZIONE (da step = 4 e 5)
      elif self.step == 6: # 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) == unicode:
            if value == QadMsg.translate("Command_ROTATE", "Points") or value == "Points":
               # imposto il map tool
               self.getPointMapTool().setMode(Qad_rotate_maptool_ModeEnum.ASK_FOR_FIRST_NEW_ROTATION_PT)
               # si appresta ad attendere un punto
               self.waitForPoint(QadMsg.translate("Command_ROTATE", "Specify first point: "))
               self.step = 7
         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)
            self.RotateGeoms(angle)
            return True # fine comando

         return False
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA PRIMO PUNTO PER NUOVO ANGOLO ROTAZIONE (da step = 6)
      elif self.step == 7: # 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.Pt1NewAng = value
         # imposto il map tool
         self.getPointMapTool().Pt1NewAng = self.Pt1NewAng
         self.getPointMapTool().setMode(Qad_rotate_maptool_ModeEnum.FIRST_PT_KNOWN_ASK_FOR_SECOND_NEW_ROTATION_PT)
         # si appresta ad attendere un punto
         self.waitForPoint(QadMsg.translate("Command_ROTATE", "Specify second point: "))
         self.step = 8
            
         return False

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA SECONDO PUNTO PER NUOVO ANGOLO ROTAZIONE (da step = 7)
      elif self.step == 8: # 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
               
         angle = qad_utils.getAngleBy2Pts(self.Pt1NewAng, value)
         
         angle = angle - self.ReferenceAng
         self.plugIn.setLastRot(angle)
         self.RotateGeoms(angle)
         return True # fine comando class QadMOVECommandClass(QadCommandClass):

   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadMOVECommandClass(self.plugIn)
   
   def getName(self):
      return QadMsg.translate("Command_list", "MOVE")

   def getEnglishName(self):
      return "MOVE"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runMOVECommand)

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/move.png")

   def getNote(self):
      # impostare le note esplicative del comando      
      return QadMsg.translate("Command_MOVE", "Moves the selected objects.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      self.SSGetClass = QadSSGetClass(plugIn)
      self.SSGetClass.onlyEditableLayers = True
      self.entitySet = QadEntitySet()
      self.basePt = QgsPoint()

   def __del__(self):
      QadCommandClass.__del__(self)
      del self.SSGetClass
      
   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      if self.step == 0: # quando si é in fase di selezione entità
         return self.SSGetClass.getPointMapTool()
      else:
         if (self.plugIn is not None):
            if self.PointMapTool is None:
               self.PointMapTool = Qad_move_maptool(self.plugIn)
            return self.PointMapTool
         else:
            return None


   def getCurrentContextualMenu(self):
      if self.step == 0: # quando si é in fase di selezione entità
         return self.SSGetClass.getCurrentContextualMenu()
      else:
         return self.contextualMenu


   #============================================================================
   # move
   #============================================================================
   def move(self, f, offSetX, offSetY, layerEntitySet, entitySet):
      # verifico se l'entità appartiene ad uno stile di quotatura
      dimEntity = QadDimStyles.getDimEntity(layerEntitySet.layer, f.id())
            
      if dimEntity is None:
         # sposto la feature e la rimuovo da entitySet (é la prima)
         f.setGeometry(qad_utils.moveQgsGeometry(f.geometry(), offSetX, offSetY))
         # plugIn, layer, feature, refresh, check_validity
         if qad_layer.updateFeatureToLayer(self.plugIn, layerEntitySet.layer, f, False, False) == False:
            return False
         del layerEntitySet.featureIds[0]
      else:
         # sposto la quota e la rimuovo da entitySet
         dimEntitySet = dimEntity.getEntitySet()
         if dimEntity.deleteToLayers(self.plugIn) == False:
            return False 
         newDimEntity = QadDimEntity(dimEntity) # la copio
         if newDimEntity.move(offSetX, offSetY) == False:
            return False             
         if newDimEntity.addToLayers(self.plugIn) == False:
            return False             
         entitySet.subtract(dimEntitySet)
            
      return True


   #============================================================================
   # moveGeoms
   #============================================================================
   def moveGeoms(self, newPt):      
      # copio entitySet
      entitySet = QadEntitySet(self.entitySet)
      
      self.plugIn.beginEditCommand("Feature moved", entitySet.getLayerList())
      
      for layerEntitySet in entitySet.layerEntitySetList:                        
         transformedBasePt = self.mapToLayerCoordinates(layerEntitySet.layer, self.basePt)
         transformedNewPt = self.mapToLayerCoordinates(layerEntitySet.layer, newPt)
         offSetX = transformedNewPt.x() - transformedBasePt.x()
         offSetY = transformedNewPt.y() - transformedBasePt.y()
         
         while len(layerEntitySet.featureIds) > 0:
            featureId = layerEntitySet.featureIds[0]
            f = layerEntitySet.getFeature(featureId)
            
            if self.move(f, offSetX, offSetY, layerEntitySet, entitySet) == False:  
               self.plugIn.destroyEditCommand()
               return
   
      self.plugIn.endEditCommand()

   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.SSGetClass.run(msgMapTool, msg) == True:
            # selezione terminata
            self.step = 1
            self.getPointMapTool().refreshSnapType() # aggiorno lo snapType che può essere variato dal maptool di selezione entità                    
            return self.run(msgMapTool, msg)
      
      #=========================================================================
      # SPOSTA OGGETTI
      elif self.step == 1:
         self.entitySet.set(self.SSGetClass.entitySet)
         
         if self.entitySet.count() == 0:
            return True # fine comando

         # imposto il map tool
         self.getPointMapTool().entitySet.set(self.entitySet)
         self.getPointMapTool().setMode(Qad_move_maptool_ModeEnum.NONE_KNOWN_ASK_FOR_BASE_PT)                                
   
         keyWords = QadMsg.translate("Command_MOVE", "Displacement")
         prompt = QadMsg.translate("Command_MOVE", "Specify base point or [{0}] <{0}>: ").format(keyWords)
         
         englishKeyWords = "Displacement"
         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 = 2      
         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
                  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 value is None or type(value) == unicode:
            self.basePt.set(0, 0)
            self.getPointMapTool().basePt = self.basePt
            self.getPointMapTool().setMode(Qad_move_maptool_ModeEnum.BASE_PT_KNOWN_ASK_FOR_MOVE_PT)                                
            # si appresta ad attendere un punto
            msg = QadMsg.translate("Command_MOVE", "Specify the displacement fom the origin point 0,0 <{0}, {1}>: ")
            # msg, inputType, default, keyWords, nessun controllo
            self.waitFor(msg.format(str(self.plugIn.lastOffsetPt.x()), str(self.plugIn.lastOffsetPt.y())), \
                         QadInputTypeEnum.POINT2D, \
                         self.plugIn.lastOffsetPt, \
                         "", QadInputModeEnum.NONE)                                      
            self.step = 4           
         elif 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().setMode(Qad_move_maptool_ModeEnum.BASE_PT_KNOWN_ASK_FOR_MOVE_PT)                                
            
            # si appresta ad attendere un punto o enter o una parola chiave         
            # msg, inputType, default, keyWords, nessun controllo
            self.waitFor(QadMsg.translate("Command_MOVE", "Specify the second point or <use first point as displacement from the origin point 0,0>: "), \
                         QadInputTypeEnum.POINT2D, \
                         None, \
                         "", QadInputModeEnum.NONE)      
            self.step = 3      
         
         return False 
         
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA SECONDO PUNTO PER SPOSTAMENTO (da step = 2)
      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 value is None:
            newPt = QgsPoint(self.basePt.x() * 2, self.basePt.y() * 2)
            self.moveGeoms(newPt)
         elif type(value) == QgsPoint: # se é stato inserito lo spostamento con un punto
            self.moveGeoms(value)
            
         return True # fine comando
               
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL PUNTO DI SPOSTAMENTO (da step = 2)
      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

         self.plugIn.setLastOffsetPt(value)
         self.moveGeoms(value)
         return True class QadSCALECommandClass(QadCommandClass):

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

   def getName(self):
      return QadMsg.translate("Command_list", "SCALE")

   def getEnglishName(self):
      return "SCALE"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runSCALECommand)

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/scale.png")

   def getNote(self):
      # impostare le note esplicative del comando      
      return QadMsg.translate("Command_SCALE", "Enlarges or reduces selected objects.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      self.SSGetClass = QadSSGetClass(plugIn)
      self.SSGetClass.onlyEditableLayers = True
      self.entitySet = QadEntitySet()
      self.basePt = None
      self.copyFeatures = False
      self.Pt1ReferenceLen = None
      self.ReferenceLen = 1
      self.Pt1NewLen = None

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

      
   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      if self.step == 0: # quando si é in fase di selezione entità
         return self.SSGetClass.getPointMapTool()
      else:
         if (self.plugIn is not None):
            if self.PointMapTool is None:
               self.PointMapTool = Qad_scale_maptool(self.plugIn)
            return self.PointMapTool
         else:
            return None


   def getCurrentContextualMenu(self):
      if self.step == 0: # quando si é in fase di selezione entità
         return self.SSGetClass.getCurrentContextualMenu()
      else:
         return self.contextualMenu


   #============================================================================
   # scale
   #============================================================================
   def scale(self, f, basePt, scale, sizeFldName, layerEntitySet, entitySet):
      # verifico se l'entità appartiene ad uno stile di quotatura
      dimEntity = QadDimStyles.getDimEntity(layerEntitySet.layer, f.id())
            
      if dimEntity is None:
         # scalo la feature e la rimuovo da entitySet (é la prima)
         f.setGeometry(qad_utils.scaleQgsGeometry(f.geometry(), basePt, scale))
         if sizeFldName is not None:
            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.copyFeatures == False:
            # plugIn, layer, feature, refresh, check_validity
            if qad_layer.updateFeatureToLayer(self.plugIn, layerEntitySet.layer, f, False, False) == False:
               self.plugIn.destroyEditCommand()
               return False
         else:             
            # plugIn, layer, features, coordTransform, refresh, check_validity
            if qad_layer.addFeatureToLayer(self.plugIn, layerEntitySet.layer, f, None, False, False) == False:
               self.plugIn.destroyEditCommand()
               return False

         del layerEntitySet.featureIds[0]
      else:
         # scalo la quota e la rimuovo da entitySet
         dimEntitySet = dimEntity.getEntitySet()
         if self.copyFeatures == False:
            if dimEntity.deleteToLayers(self.plugIn) == False:
               return False                      
         newDimEntity = QadDimEntity(dimEntity) # la copio
         newDimEntity.scale(basePt, scale)
         if newDimEntity.addToLayers(self.plugIn) == False:
            return False             
         entitySet.subtract(dimEntitySet)


   def scaleGeoms(self, scale):      
      # copio entitySet
      entitySet = QadEntitySet(self.entitySet)
      
      self.plugIn.beginEditCommand("Feature scaled", self.entitySet.getLayerList())
      
      for layerEntitySet in entitySet.layerEntitySetList:
         layer = layerEntitySet.layer
                              
         transformedBasePt = self.mapToLayerCoordinates(layer, self.basePt)
         
         sizeFldName = None
         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)
            if len(sizeFldName) == 0:
               sizeFldName = None

         while len(layerEntitySet.featureIds) > 0:
            featureId = layerEntitySet.featureIds[0]
            f = layerEntitySet.getFeature(featureId)

            if self.scale(f, transformedBasePt, scale, sizeFldName, layerEntitySet, entitySet) == False:  
               self.plugIn.destroyEditCommand()
               return

      self.plugIn.endEditCommand()


   def waitForScale(self):
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_scale_maptool_ModeEnum.BASE_PT_KNOWN_ASK_FOR_SCALE_PT)

      keyWords = QadMsg.translate("Command_SCALE", "Copy") + "/" + \
                 QadMsg.translate("Command_SCALE", "Reference")
      default = self.plugIn.lastScale
      prompt = QadMsg.translate("Command_SCALE", "Specify scale factor or [{0}] <{1}>: ").format(keyWords, str(default))                        
      
      englishKeyWords = "Copy" + "/" + "Reference"
      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, \
                   default, \
                   keyWords, QadInputModeEnum.NOT_ZERO | QadInputModeEnum.NOT_NEGATIVE)      
      self.step = 3      


   def waitForReferenceLen(self):
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_scale_maptool_ModeEnum.ASK_FOR_FIRST_PT_REFERENCE_LEN)
      
      msg = QadMsg.translate("Command_SCALE", "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 = 4


   def waitForNewReferenceLen(self):
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_scale_maptool_ModeEnum.BASE_PT_KNOWN_ASK_FOR_NEW_LEN_PT)
      
      keyWords = QadMsg.translate("Command_SCALE", "Points")
      if self.plugIn.lastNewReferenceLen == 0:
         default = self.plugIn.lastScale
      else:
         default = self.plugIn.lastNewReferenceLen
      prompt = QadMsg.translate("Command_SCALE", "Specify new length or [{0}] <{1}>: ").format(keyWords, str(default))                        
         
      englishKeyWords = "Points"
      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, \
                   default, \
                   keyWords, QadInputModeEnum.NOT_ZERO | QadInputModeEnum.NOT_NEGATIVE)
      self.step = 6
   

   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.SSGetClass.run(msgMapTool, msg) == True:
            # selezione terminata
            self.step = 1
            self.getPointMapTool().refreshSnapType() # aggiorno lo snapType che può essere variato dal maptool di selezione entità                    
            return self.run(msgMapTool, msg)
      
      #=========================================================================
      # RUOTA OGGETTI
      elif self.step == 1:
         self.entitySet.set(self.SSGetClass.entitySet)
         
         if self.entitySet.count() == 0:
            return True # fine comando

         # 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_SCALE", "Specify base point: "))
                  
         self.step = 2     
         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
         self.getPointMapTool().entitySet.set(self.entitySet)
         # si appresta ad attendere la scala                      
         self.waitForScale()
         
         return False 
         
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA SECONDO PUNTO PER SCALA (da step = 2)
      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) == unicode:
            if value == QadMsg.translate("Command_SCALE", "Copy") or value == "Copy":
               self.copyFeatures = True
               self.showMsg(QadMsg.translate("Command_SCALE", "\nScale of a copy of the selected objects."))
               # si appresta ad attendere la scala               
               self.waitForScale()                
            elif value == QadMsg.translate("Command_SCALE", "Reference") or value == "Reference":
               # si appresta ad attendere la lunghezza di riferimento                      
               self.waitForReferenceLen()
         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
            self.plugIn.setLastScale(scale)

            self.scaleGeoms(scale)
            return True # fine comando
         
         return False
               
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA PRIMO PUNTO PER LUNGHEZZA DI RIFERIMENTO (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) == float: # se é stato inserita la lunghezza
            self.ReferenceLen = value
            self.getPointMapTool().ReferenceLen = self.ReferenceLen 
            # si appresta ad attendere la nuova lunghezza                    
            self.waitForNewReferenceLen()

         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_SCALE", "Specify second point: "))
            self.step = 5           
            
         return False

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA SECONDO PUNTO PER LUNGHEZZA DI RIFERIMENTO (da step = 4)
      elif self.step == 5: # 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_SCALE", "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.waitForNewReferenceLen()
            
         return False

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA SECONDO PUNTO PER NUOVA LUNGHEZZA (da step = 4 e 5)
      elif self.step == 6: # 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) == unicode:
            if value == QadMsg.translate("Command_SCALE", "Points") or value == "Points":
               # imposto il map tool
               self.getPointMapTool().setMode(Qad_scale_maptool_ModeEnum.ASK_FOR_FIRST_NEW_LEN_PT)
               # si appresta ad attendere un punto
               self.waitForPoint(QadMsg.translate("Command_SCALE", "Specify first point: "))
               self.step = 7
         elif type(value) == QgsPoint or type(value) == float: # se é stato inserita la lunghezza
            if type(value) == QgsPoint: # se é stato inserito la lunghezza 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.waitForNewReferenceLen()
                  return False
                                       
               length = qad_utils.getDistance(self.basePt, value)
            else:
               length = value
            
            scale = length / self.ReferenceLen
            self.plugIn.setLastScale(scale)
            self.scaleGeoms(scale)
            return True # fine comando

         return False
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA PRIMO PUNTO PER NUOVA LUNGHEZZA (da step = 6)
      elif self.step == 7: # 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.Pt1NewLen = value
         # imposto il map tool
         self.getPointMapTool().Pt1NewLen = self.Pt1NewLen
         self.getPointMapTool().setMode(Qad_scale_maptool_ModeEnum.FIRST_PT_KNOWN_ASK_FOR_SECOND_NEW_LEN_PT)
         # si appresta ad attendere un punto
         self.waitForPoint(QadMsg.translate("Command_SCALE", "Specify second point: "))
         self.step = 8
            
         return False

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA SECONDO PUNTO PER NUOVA LUNGHEZZA (da step = 7)
      elif self.step == 8: # 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 value == self.Pt1NewLen:
            self.showMsg(QadMsg.translate("QAD", "\nThe value must be positive and not zero."))
            # si appresta ad attendere un punto
            self.waitForPoint(QadMsg.translate("Command_SCALE", "Specify second point: "))
            return False
               
         length = qad_utils.getDistance(self.Pt1NewLen, value)
         
         scale = length / self.ReferenceLen
         self.plugIn.setLastScale(scale)
         self.scaleGeoms(scale)
         return True # fine comando class QadCOPYCommandClass(QadCommandClass):

   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadCOPYCommandClass(self.plugIn)
   
   def getName(self):
      return QadMsg.translate("Command_list", "COPY")

   def getEnglishName(self):
      return "COPY"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runCOPYCommand)

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/copyEnt.png")

   def getNote(self):
      # impostare le note esplicative del comando
      return QadMsg.translate("Command_COPY", "Copies selected objects a specified distance in a specified direction.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      self.SSGetClass = QadSSGetClass(plugIn)
      self.SSGetClass.onlyEditableLayers = True
      self.entitySet = QadEntitySet()
      self.basePt = QgsPoint()
      self.series = False
      self.seriesLen = 2
      self.adjust = False
      self.copyMode = QadVariables.get(QadMsg.translate("Environment variables", "COPYMODE"))
      
      self.featureCache = [] # lista di (layer, feature)
      self.nOperationsToUndo = 0

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


   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      if self.step == 0: # quando si é in fase di selezione entità
         return self.SSGetClass.getPointMapTool()
      else:
         if (self.plugIn is not None):
            if self.PointMapTool is None:
               self.PointMapTool = Qad_copy_maptool(self.plugIn)
            return self.PointMapTool
         else:
            return None


   def getCurrentContextualMenu(self):
      if self.step == 0: # quando si é in fase di selezione entità
         return self.SSGetClass.getCurrentContextualMenu()
      else:
         return self.contextualMenu


   #============================================================================
   # move
   #============================================================================
   def move(self, f, offSetX, offSetY, layerEntitySet, entitySet, dimEntity):
      if dimEntity is None:
         # sposto la feature e la rimuovo da entitySet (é la prima)
         f.setGeometry(qad_utils.moveQgsGeometry(f.geometry(), offSetX, offSetY))
         # plugIn, layer, feature, coordTransform, refresh, check_validity
         if qad_layer.addFeatureToLayer(self.plugIn, layerEntitySet.layer, f, None, False, False) == False:  
            return False
      else:
         newDimEntity = QadDimEntity(dimEntity) # la copio
         # sposto la quota
         newDimEntity.move(offSetX, offSetY)
         if newDimEntity.addToLayers(self.plugIn) == False:
            return False             
            
      return True


   #============================================================================
   # copyGeoms
   #============================================================================
   def copyGeoms(self, newPt):
      # copio entitySet
      entitySet = QadEntitySet(self.entitySet)
      
      self.plugIn.beginEditCommand("Feature copied", entitySet.getLayerList())

      for layerEntitySet in entitySet.layerEntitySetList:
         layer = layerEntitySet.layer
         
         transformedBasePt = self.mapToLayerCoordinates(layer, self.basePt)
         transformedNewPt = self.mapToLayerCoordinates(layer, newPt)
         offSetX = transformedNewPt.x() - transformedBasePt.x()
         offSetY = transformedNewPt.y() - transformedBasePt.y()
         
         while len(layerEntitySet.featureIds) > 0:
            featureId = layerEntitySet.featureIds[0]
            f = layerEntitySet.getFeature(featureId)
            if f is None:
               del layerEntitySet.featureIds[0]
               continue

            # verifico se l'entità appartiene ad uno stile di quotatura
            dimEntity = QadDimStyles.getDimEntity(layerEntitySet.layer, f.id())
            
            if self.series and self.seriesLen > 0: # devo fare una serie
               if self.adjust == True:
                  offSetX = offSetX / (self.seriesLen - 1)
                  offSetY = offSetY / (self.seriesLen - 1)
   
               deltaX = offSetX
               deltaY = offSetY
                              
               for i in xrange(1, self.seriesLen, 1):
                  if self.move(f, deltaX, deltaY, layerEntitySet, entitySet, dimEntity) == False:
                     self.plugIn.destroyEditCommand()
                     return
                  deltaX = deltaX + offSetX
                  deltaY = deltaY + offSetY
            else:
               if self.move(f, offSetX, offSetY, layerEntitySet, entitySet, dimEntity) == False:
                  self.plugIn.destroyEditCommand()
                  return
               
            # la rimuovo da entitySet
            if dimEntity is None:
               del layerEntitySet.featureIds[0]
            else:
               dimEntitySet = dimEntity.getEntitySet()
               entitySet.subtract(dimEntitySet)
               
      self.plugIn.endEditCommand()
      self.nOperationsToUndo = self.nOperationsToUndo + 1


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

      if self.copyMode == 0: # Imposta il comando COPIA in modo che venga ripetuto automaticamente
         keyWords = QadMsg.translate("Command_COPY", "Displacement") + "/" + \
                    QadMsg.translate("Command_COPY", "mOde")
         englishKeyWords = "Displacement" + "/" + "mOde"
                    
      else:
         # l'opzione Multiple viene tradotta in italiano in "MUltiplo" nel contesto "waitForBasePt"
         # l'opzione Multiple viene tradotta in italiano in "Multipla" nel contesto "waitForMode"
         # e "Multipla" nel caso di modalità di copia
         keyWords = QadMsg.translate("Command_COPY", "Displacement") + "/" + \
                    QadMsg.translate("Command_COPY", "mOde") + "/" + \
                    QadMsg.translate("Command_COPY", "Multiple", "waitForBasePt")
         englishKeyWords = "Displacement" + "/" + "mOde" + "/" + "Multiple"

      default = QadMsg.translate("Command_COPY", "Displacement")                   
      prompt = QadMsg.translate("Command_COPY", "Specify base point or [{0}] <{1}>: ").format(keyWords, default)
      
      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, \
                   default, \
                   keyWords, QadInputModeEnum.NONE)      
      self.step = 2      
   
   #============================================================================
   # waitForSeries
   #============================================================================
   def waitForSeries(self):
      # si appresta ad attendere un numero intero
      msg = QadMsg.translate("Command_COPY", "Number of Items to Array <{0}>: ")
      # msg, inputType, default, keyWords, valori positivi
      self.waitFor(msg.format(str(self.seriesLen)), \
                   QadInputTypeEnum.INT, \
                   self.seriesLen, \
                   "", \
                   QadInputModeEnum.NOT_ZERO | QadInputModeEnum.NOT_NEGATIVE)                                      
      self.step = 6        
      
   #============================================================================
   # waitForSecondPt
   #============================================================================
   def waitForSecondPt(self):
      self.series = False
      self.adjust = False
      self.getPointMapTool().seriesLen = 0
      self.getPointMapTool().setMode(Qad_copy_maptool_ModeEnum.BASE_PT_KNOWN_ASK_FOR_COPY_PT)
                                      
      if len(self.featureCache) > 0:
         keyWords = QadMsg.translate("Command_COPY", "Array") + "/" + \
                    QadMsg.translate("Command_COPY", "Exit") + "/" + \
                    QadMsg.translate("Command_COPY", "Undo")
         default = QadMsg.translate("Command_COPY", "Exit")
         prompt = QadMsg.translate("Command_COPY", "Specify second point or [{0}] <{1}>: ").format(keyWords, default)
   
         englishKeyWords = "Array" + "/" + "Exit" + "/" + "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, \
                      default, \
                      keyWords, QadInputModeEnum.NONE)
      else:
         keyWords = QadMsg.translate("Command_COPY", "Array")
         prompt = QadMsg.translate("Command_COPY", "Specify second point or [{0}] <use first point as displacement from origin point 0,0>: ").format(keyWords)
                   
         englishKeyWords = "Array"
         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 = 3           

   #============================================================================
   # waitForSecondPtBySeries
   #============================================================================
   def waitForSecondPtBySeries(self):
      if self.adjust == False:
         keyWords = QadMsg.translate("Command_COPY", "Fit")
         englishKeyWords = "Fit"        
      else:
         keyWords = QadMsg.translate("Command_COPY", "Array")
         englishKeyWords = "Array"        
      prompt = QadMsg.translate("Command_COPY", "Specify second point or [{0}]: ").format(keyWords)

      keyWords += "_" + englishKeyWords
      # si appresta ad attendere un punto o enter o una parola chiave         
      # msg, inputType, default, keyWords, valore nullo non permesso
      self.waitFor(prompt, \
                   QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS, \
                   "", \
                   keyWords, QadInputModeEnum.NOT_NULL)      
      self.step = 7

   #============================================================================
   # 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.SSGetClass.run(msgMapTool, msg) == True:
            # selezione terminata
            self.step = 1
            return self.run(msgMapTool, msg)
      
      #=========================================================================
      # COPIA OGGETTI
      elif self.step == 1:
         self.entitySet.set(self.SSGetClass.entitySet)
         
         if self.entitySet.count() == 0:
            return True # fine comando

         CurrSettingsMsg = QadMsg.translate("QAD", "\nCurrent settings: ")
         if self.copyMode == 0: # 0 = multipla 
            CurrSettingsMsg = CurrSettingsMsg + QadMsg.translate("Command_COPY", "Copy mode = Multiple")         
         else: # 1 = singola
            CurrSettingsMsg = CurrSettingsMsg + QadMsg.translate("Command_COPY", "Copy mode = Single")         
         self.showMsg(CurrSettingsMsg)         

         self.getPointMapTool().entitySet.set(self.entitySet)
         self.waitForBasePt()
         self.getPointMapTool().refreshSnapType() # riagggiorno lo snapType che può essere variato dal maptool di selezione entità                    
         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
                  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 value is None:
            value = QadMsg.translate("Command_COPY", "Displacement")

         if type(value) == unicode:
            if value == QadMsg.translate("Command_COPY", "Displacement") or value == "Displacement":
               self.basePt.set(0, 0)
               self.getPointMapTool().basePt = self.basePt
               self.getPointMapTool().setMode(Qad_copy_maptool_ModeEnum.BASE_PT_KNOWN_ASK_FOR_COPY_PT)                                
               # si appresta ad attendere un punto
               msg = QadMsg.translate("Command_COPY", "Specify the displacement from the origin point 0,0 <{0}, {1}>: ")
               # msg, inputType, default, keyWords, nessun controllo
               self.waitFor(msg.format(str(self.plugIn.lastOffsetPt.x()), str(self.plugIn.lastOffsetPt.y())), \
                            QadInputTypeEnum.POINT2D, \
                            self.plugIn.lastOffsetPt, \
                            "", QadInputModeEnum.NONE)                                      
               self.step = 4
            elif value == QadMsg.translate("Command_COPY", "mOde") or value == "mOde":
               # l'opzione Multiple viene tradotta in italiano in "Multipla" nel contesto "waitForMode"
               keyWords = QadMsg.translate("Command_COPY", "Single") + "/" + \
                          QadMsg.translate("Command_COPY", "Multiple", "waitForMode")
               englishKeyWords = "Single" + "/" + "Multiple"
                          
               if self.copyMode == 0: # Imposta il comando COPIA in modo che venga ripetuto automaticamente
                  # l'opzione Multiple viene tradotta in italiano in "Multipla" nel contesto "waitForMode"
                  default = QadMsg.translate("Command_COPY", "Multiple", "waitForMode")
               else:
                  default = QadMsg.translate("Command_COPY", "Single")               
               prompt = QadMsg.translate("Command_COPY", "Enter a copy mode option [{0}] <{1}>: ").format(keyWords, default)

               keyWords += "_" + englishKeyWords
               # si appresta ad attendere enter o una parola chiave         
               # msg, inputType, default, keyWords, nessun controllo
               self.waitFor(prompt, \
                            QadInputTypeEnum.KEYWORDS, \
                            default, \
                            keyWords, QadInputModeEnum.NONE)
               self.step = 5
            # l'opzione Multiple viene tradotta in italiano in "MUltiplo" nel contesto "waitForBasePt"
            elif value == QadMsg.translate("Command_COPY", "Multiple", "waitForBasePt") or value == "Multiple":
               self.copyMode = 0 # Imposta il comando COPIA in modo che venga ripetuto automaticamente
               self.waitForBasePt()                         
         elif 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.waitForSecondPt()
         
         return False 
         
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA SECONDO PUNTO PER COPIA (da step = 2)
      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
                  if len(self.featureCache) > 0:
                     value = QadMsg.translate("Command_COPY", "Exit")
                  else:
                     value = None
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False
            else:
               value = self.getPointMapTool().point
         else: # il punto arriva come parametro della funzione
            value = msg

         if value is None:
            if len(self.featureCache) > 0:
               value = QadMsg.translate("Command_COPY", "Exit")
            else:               
               # utilizzare il primo punto come spostamento
               value = QgsPoint(self.basePt)
               self.basePt.set(0, 0)
               self.copyGeoms(value)
               return True # fine comando
         
         if type(value) == unicode:
            if value == QadMsg.translate("Command_COPY", "Array") or value == "Array":
               self.waitForSeries()               
            elif value == QadMsg.translate("Command_COPY", "Exit") or value == "Exit":
               return True # fine comando
            elif value == QadMsg.translate("Command_COPY", "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.waitForSecondPt()
         elif type(value) == QgsPoint: # se é stato inserito lo spostamento con un punto
            self.copyGeoms(value)
            if self.copyMode == 1: # "Singola" 
               return True # fine comando
            self.waitForSecondPt()
         
         return False
               
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL PUNTO DI SPOSTAMENTO (da step = 2)
      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

         self.plugIn.setLastOffsetPt(value)
         self.copyGeoms(value)
         return True # fine comando


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DELLA MODALITA' (SINGOLA / MULTIPLA) (da step = 2)
      elif self.step == 5: # 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: # la parola chiave arriva come parametro della funzione
            value = msg

         if type(value) == unicode:
            if value == QadMsg.translate("Command_COPY", "Single") or value == "Single":
               self.copyMode = 1
               QadVariables.set(QadMsg.translate("Environment variables", "COPYMODE"), 1)
               QadVariables.save()
            # l'opzione Multiple viene tradotta in italiano in "Multipla" nel contesto "waitForMode"
            elif value == QadMsg.translate("Command_COPY", "Multiple", "waitForMode") or value == "Multiple":
               self.copyMode = 0
               QadVariables.set(QadMsg.translate("Environment variables", "COPYMODE"), 0)
               QadVariables.save()
            
         self.waitForBasePt()
         return False

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DELLA SERIE (da step = 3)
      elif self.step == 6: # dopo aver atteso un numero intero si riavvia il comando
         if msgMapTool == True: # il punto arriva da una selezione grafica
            if self.getPointMapTool().rightButton == True: # se usato il tasto destro del mouse
               value = self.seriesLen
            else:
               value = self.getPointMapTool().point
         else: # il punto arriva come parametro della funzione
            value = msg

         if value < 2:
            self.showMsg(QadMsg.translate("Command_COPY", "\nThe value must be between 2 and 32767."))
            self.waitForSeries()
         else:
            self.series = True
            self.seriesLen = value
            self.getPointMapTool().seriesLen = self.seriesLen

            self.waitForSecondPtBySeries()
            
         return False

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA SECONDO PUNTO PER COPIA DA SERIE (da step = 6)
      elif self.step == 7: # dopo aver atteso un punto o una parola chiave
         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) == unicode:
            if value == QadMsg.translate("Command_COPY", "Array") or value == "Array":
               self.adjust = False
               self.getPointMapTool().adjust = self.adjust
               self.waitForSecondPtBySeries()
            elif value == QadMsg.translate("Command_COPY", "Fit") or value == "Fit":
               self.adjust = True
               self.getPointMapTool().adjust = self.adjust
               self.waitForSecondPtBySeries()
         elif type(value) == QgsPoint: # se é stato inserito lo spostamento con un punto
            self.copyGeoms(value)
            if self.copyMode == 1: # "Singola" 
               return True # fine comando            
            self.waitForSecondPt()
          
         return False class QadOFFSETCommandClass(QadCommandClass):

   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadOFFSETCommandClass(self.plugIn)
   
   def getName(self):
      return QadMsg.translate("Command_list", "OFFSET")

   def getEnglishName(self):
      return "OFFSET"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runOFFSETCommand)

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/offset.png")

   def getNote(self):
      # impostare le note esplicative del comando
      return QadMsg.translate("Command_OFFSET", "Creates concentric circles, parallel lines, and parallel curves.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      self.entity = QadEntity()
      self.subGeom = None
      self.subGeomSelectedPt = None
      self.offSet = QadVariables.get(QadMsg.translate("Environment variables", "OFFSETDIST"))
      self.lastOffSetOnLeftSide = 0
      self.lastOffSetOnRightSide = 0
      self.firstPt = QgsPoint()
      self.eraseEntity = False
      self.multi = False
      self.OnlySegment = False
      self.gapType = QadVariables.get(QadMsg.translate("Environment variables", "OFFSETGAPTYPE"))
      
      self.featureCache = [] # lista di (layer, feature)
      self.undoFeatureCacheIndexes = [] # posizioni in featureCache dei punti di undo
      self.rubberBand = createRubberBand(self.plugIn.canvas, QGis.Line)
      self.rubberBandPolygon = createRubberBand(self.plugIn.canvas, QGis.Polygon)

   def __del__(self):
      QadCommandClass.__del__(self)
      self.rubberBand.hide()
      self.plugIn.canvas.scene().removeItem(self.rubberBand)
      self.rubberBandPolygon.hide()
      self.plugIn.canvas.scene().removeItem(self.rubberBandPolygon)
      
   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      if (self.plugIn is not None):
         if self.PointMapTool is None:
            self.PointMapTool = Qad_offset_maptool(self.plugIn)
         return self.PointMapTool
      else:
         return None

   #============================================================================
   # addFeatureCache
   #============================================================================
   def addFeatureCache(self, newPt):
      featureCacheLen = len(self.featureCache)
      layer = self.entity.layer
      f = self.entity.getFeature()

      # ritorna una tupla (<The squared cartesian distance>,
      #                    <minDistPoint>
      #                    <afterVertex>
      #                    <leftOf>)
      dummy = qad_utils.closestSegmentWithContext(newPt, self.subGeom)
      if self.offSet < 0:
         afterVertex = dummy[2]
         pt = qad_utils.getPerpendicularPointOnInfinityLine(self.subGeom.vertexAt(afterVertex - 1), \
                                                            self.subGeom.vertexAt(afterVertex), \
                                                            newPt)
         offSetDistance = qad_utils.getDistance(newPt, pt)
      else:        
         offSetDistance = self.offSet                     
         if self.multi == True:
            if dummy[3] < 0: # alla sinistra
               offSetDistance = offSetDistance + self.lastOffSetOnLeftSide
               self.lastOffSetOnLeftSide = offSetDistance
               self.getPointMapTool().lastOffSetOnLeftSide = self.lastOffSetOnLeftSide
            else: # alla destra
               offSetDistance = offSetDistance + self.lastOffSetOnRightSide
               self.lastOffSetOnRightSide = offSetDistance            
               self.getPointMapTool().lastOffSetOnRightSide = self.lastOffSetOnRightSide

      tolerance2ApproxCurve = QadVariables.get(QadMsg.translate("Environment variables", "TOLERANCE2APPROXCURVE"))
      # uso il crs del canvas per lavorare con coordinate piane xy
      epsg = self.plugIn.canvas.mapSettings().destinationCrs().authid()
      lines = qad_utils.offSetPolyline(self.subGeom.asPolyline(), epsg, \
                                       offSetDistance, \
                                       "left" if dummy[3] < 0 else "right", \
                                       self.gapType, \
                                       tolerance2ApproxCurve)
      added = False
      for line in lines:        
         if layer.geometryType() == QGis.Polygon:
            if line[0] == line[-1]: # se é una linea chiusa
               offsetGeom = QgsGeometry.fromPolygon([line])
            else:
               offsetGeom = QgsGeometry.fromPolyline(line)
         else:
            offsetGeom = QgsGeometry.fromPolyline(line)

         if offsetGeom.type() == QGis.Line or offsetGeom.type() == QGis.Polygon:           
            offsetFeature = QgsFeature(f)
            # trasformo la geometria nel crs del layer
            offsetFeature.setGeometry(self.mapToLayerCoordinates(layer, offsetGeom))
            self.featureCache.append([layer, offsetFeature])
            self.addFeatureToRubberBand(layer, offsetFeature)            
            added = True           

      if added:      
         self.undoFeatureCacheIndexes.append(featureCacheLen)


   #============================================================================
   # undoGeomsInCache
   #============================================================================
   def undoGeomsInCache(self):
      tot = len(self.featureCache)
      if tot > 0:
         iEnd = self.undoFeatureCacheIndexes[-1]
         i = tot - 1
         
         del self.undoFeatureCacheIndexes[-1] # cancello ultimo undo
         while i >= iEnd:
            del self.featureCache[-1] # cancello feature
            i = i - 1
         self.refreshRubberBand()

            
   #============================================================================
   # addFeatureToRubberBand
   #============================================================================
   def addFeatureToRubberBand(self, layer, feature):
      if layer.geometryType() == QGis.Polygon:
         if feature.geometry().type() == QGis.Polygon:
            self.rubberBandPolygon.addGeometry(feature.geometry(), layer)
         else:
            self.rubberBand.addGeometry(feature.geometry(), layer)
      else:
         self.rubberBand.addGeometry(feature.geometry(), layer)
      
      
   #============================================================================
   # refreshRubberBand
   #============================================================================
   def refreshRubberBand(self):
      self.rubberBand.reset(QGis.Line)
      self.rubberBandPolygon.reset(QGis.Polygon)
      for f in self.featureCache:
         layer = f[0]
         feature = f[1]
         if layer.geometryType() == QGis.Polygon:
            if feature.geometry().type() == QGis.Polygon:
               self.rubberBandPolygon.addGeometry(feature.geometry(), layer)
            else:
               self.rubberBand.addGeometry(feature.geometry(), layer)            
         else:
            self.rubberBand.addGeometry(feature.geometry(), layer)            


   #============================================================================
   # offsetGeoms
   #============================================================================
   def offsetGeoms(self, currLayer):
      featuresLayers = [] # lista di (layer, features)
      
      for f in self.featureCache:
         layer = f[0]
         feature = f[1]
         found = False
         for featuresLayer in featuresLayers:
            if featuresLayer[0].id() == layer.id():
               found = True
               featuresLayer[1].append(feature)
               break
         # se non c'era ancora il layer
         if not found:
            featuresLayers.append([layer, [feature]])

      layerList = []
      for featuresLayer in featuresLayers:
         layerList.append(featuresLayer[0])

      PointTempLayer = None
      LineTempLayer = None
      PolygonTempLayer = None
      self.plugIn.beginEditCommand("Feature offseted", layerList)

      for featuresLayer in featuresLayers:
         # filtro le features per tipo
         pointGeoms, lineGeoms, polygonGeoms = qad_utils.filterFeaturesByType(featuresLayer[1], \
                                                                              currLayer.geometryType())
         # aggiungo le features con geometria del tipo corretto
         if currLayer.geometryType() == QGis.Line:
            polygonToLines = []
            # Riduco le geometrie in linee
            for g in polygonGeoms:
               lines = qad_utils.asPointOrPolyline(g)
               for l in lines:
                  if l.type() == QGis.Line:
                      polygonToLines.append(l)
            # plugIn, layer, geoms, coordTransform , refresh, check_validity
            if qad_layer.addGeomsToLayer(self.plugIn, currLayer, polygonToLines, None, False, False) == False:
               self.plugIn.destroyEditCommand()
               return
               
            del polygonGeoms[:] # svuoto la lista

         # plugIn, layer, features, coordTransform, refresh, check_validity
         if qad_layer.addFeaturesToLayer(self.plugIn, currLayer, featuresLayer[1], None, False, False) == False:
            self.plugIn.destroyEditCommand()
            return

         if pointGeoms is not None and len(pointGeoms) > 0 and PointTempLayer is None:
            PointTempLayer = qad_layer.createQADTempLayer(self.plugIn, QGis.Point)
            self.plugIn.addLayerToLastEditCommand("Feature offseted", PointTempLayer)
         
         if lineGeoms is not None and len(lineGeoms) > 0 and LineTempLayer is None:
            LineTempLayer = qad_layer.createQADTempLayer(self.plugIn, QGis.Line)
            self.plugIn.addLayerToLastEditCommand("Feature offseted", LineTempLayer)
            
         if polygonGeoms is not None and len(polygonGeoms) > 0 and PolygonTempLayer is None:
            PolygonTempLayer = qad_layer.createQADTempLayer(self.plugIn, QGis.Polygon)
            self.plugIn.addLayerToLastEditCommand("Feature offseted", PolygonTempLayer)
         
         # aggiungo gli scarti nei layer temporanei di QAD
         # trasformo la geometria in quella dei layer temporanei 
         # plugIn, pointGeoms, lineGeoms, polygonGeoms, coord, refresh
         if qad_layer.addGeometriesToQADTempLayers(self.plugIn, pointGeoms, lineGeoms, polygonGeoms, \
                                                 featuresLayer[0].crs(), False) == False:
            self.plugIn.destroyEditCommand()
            return

      self.plugIn.endEditCommand()

 
   #============================================================================
   # waitForDistance
   #============================================================================
   def waitForDistance(self):      
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_offset_maptool_ModeEnum.ASK_FOR_FIRST_OFFSET_PT)
      self.getPointMapTool().gapType = self.gapType                        

      keyWords = QadMsg.translate("Command_OFFSET", "Through") + "/" + \
                 QadMsg.translate("Command_OFFSET", "Erase")                
      if self.offSet < 0:
         default = QadMsg.translate("Command_OFFSET", "Through")
      else:
         default = self.offSet
      prompt = QadMsg.translate("Command_OFFSET", "Specify the offset distance or [{0}] <{1}>: ").format(keyWords, str(default))

      englishKeyWords = "Through" + "/" + "Erase"
      keyWords += "_" + englishKeyWords
      # si appresta ad attendere un punto o enter o una parola chiave o un numero reale     
      # msg, inputType, default, keyWords, nessun controllo
      self.waitFor(prompt, \
                   QadInputTypeEnum.POINT2D | QadInputTypeEnum.FLOAT | QadInputTypeEnum.KEYWORDS, \
                   default, \
                   keyWords, \
                   QadInputModeEnum.NOT_ZERO | QadInputModeEnum.NOT_NEGATIVE)      
      self.step = 1      
   
   #============================================================================
   # waitForObjectSel
   #============================================================================
   def waitForObjectSel(self):      
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_offset_maptool_ModeEnum.ASK_FOR_ENTITY_SELECTION)                                      
      self.lastOffSetOnLeftSide = 0
      self.getPointMapTool().lastOffSetOnLeftSide = self.lastOffSetOnLeftSide
      self.lastOffSetOnRightSide = 0
      self.getPointMapTool().lastOffSetOnRightSide = self.lastOffSetOnRightSide
      
      # "Esci" "ANnulla"      
      keyWords = QadMsg.translate("Command_OFFSET", "Exit") + "/" + \
                 QadMsg.translate("Command_OFFSET", "Undo")
      default = QadMsg.translate("Command_OFFSET", "Exit")
      prompt = QadMsg.translate("Command_OFFSET", "Select object to offset or [{0}] <{1}>: ").format(keyWords, default)
      
      englishKeyWords = "Exit" + "/" + "Undo"
      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, \
                   default, \
                   keyWords, QadInputModeEnum.NONE)      
      self.step = 2      
        
   #============================================================================
   # waitForSidePt
   #============================================================================
   def waitForSidePt(self):      
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_offset_maptool_ModeEnum.OFFSET_KNOWN_ASK_FOR_SIDE_PT)                                

      if self.multi == False:
         keyWords = QadMsg.translate("Command_OFFSET", "Exit") + "/" + \
                    QadMsg.translate("Command_OFFSET", "Multiple") + "/" + \
                    QadMsg.translate("Command_OFFSET", "Undo")
         defaultMsg = QadMsg.translate("Command_OFFSET", "Exit")        
         default = QadMsg.translate("Command_OFFSET", "Exit")
         englishKeyWords = "Exit" + "/" + "Multiple" + "/" + "Undo"
      else:
         keyWords = QadMsg.translate("Command_OFFSET", "Exit") + "/" + \
                    QadMsg.translate("Command_OFFSET", "Undo")
         defaultMsg = QadMsg.translate("Command_OFFSET", "next object")
         default = None
         englishKeyWords = "Exit" + "/" + "Undo"

      if self.OnlySegment == False:
         keyWords = keyWords + "/" + \
                    QadMsg.translate("Command_OFFSET", "Segment")
         englishKeyWords = englishKeyWords + "/" + "Segment"

      prompt = QadMsg.translate("Command_OFFSET", "Specify point on side to offset or [{0}] <{1}>: ")

      keyWords += "_" + englishKeyWords
      # si appresta ad attendere un punto o enter o una parola chiave         
      # msg, inputType, default, keyWords, valore nullo non permesso
      self.waitFor(prompt.format(keyWords, defaultMsg), \
                   QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS, \
                   default, \
                   keyWords, QadInputModeEnum.NONE)      
      self.step = 3
        
   #============================================================================
   # waitForPassagePt
   #============================================================================
   def waitForPassagePt(self):
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_offset_maptool_ModeEnum.ASK_FOR_PASSAGE_PT)                                

      if self.multi == False:
         keyWords = QadMsg.translate("Command_OFFSET", "Exit") + "/" + \
                    QadMsg.translate("Command_OFFSET", "Multiple") + "/" + \
                    QadMsg.translate("Command_OFFSET", "Undo")
         defaultMsg = QadMsg.translate("Command_OFFSET", "Exit")        
         default = QadMsg.translate("Command_OFFSET", "Exit")
         englishKeyWords = "Exit" + "/" + "Multiple" + "/" + "Undo"
      else:
         keyWords = QadMsg.translate("Command_OFFSET", "Exit") + "/" + \
                    QadMsg.translate("Command_OFFSET", "Undo")
         defaultMsg = QadMsg.translate("Command_OFFSET", "next object")
         default = None
         englishKeyWords = "Exit" + "/" + "Undo"

      if self.OnlySegment == False:
         keyWords = keyWords + "/" + \
                    QadMsg.translate("Command_OFFSET", "Segment")
         englishKeyWords = englishKeyWords + "/" + "Segment"

      prompt = QadMsg.translate("Command_OFFSET", "Specify through point or [{0}] <{1}>: ")

      keyWords += "_" + englishKeyWords
      # si appresta ad attendere un punto o enter o una parola chiave         
      # msg, inputType, default, keyWords, valore nullo non permesso
      self.waitFor(prompt.format(keyWords, defaultMsg), \
                   QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS, \
                   default, \
                   keyWords, QadInputModeEnum.NONE)      
      self.step = 4

   #============================================================================
   # 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

      # il layer corrente deve essere editabile e di tipo linea o poligono
      currLayer, errMsg = qad_layer.getCurrLayerEditable(self.plugIn.canvas, [QGis.Line, QGis.Polygon])
      if currLayer is None:
         self.showErr(errMsg)
         return True # fine comando

      #=========================================================================
      # RICHIESTA DISTANZA DI OFFSET
      if self.step == 0: # inizio del comando
         CurrSettingsMsg = QadMsg.translate("QAD", "\nCurrent settings: ")
         CurrSettingsMsg = CurrSettingsMsg + QadMsg.translate("Command_OFFSET", "OFFSETGAPTYPE = ") + str(self.gapType)                        
         if self.gapType == 0:
            CurrSettingsMsg = CurrSettingsMsg + QadMsg.translate("Command_OFFSET", " (extends the segments)")
         elif self.gapType == 1:
            CurrSettingsMsg = CurrSettingsMsg + QadMsg.translate("Command_OFFSET", " (fillets the segments)")
         elif self.gapType == 2:
            CurrSettingsMsg = CurrSettingsMsg + QadMsg.translate("Command_OFFSET", " (chamfers the segments)")
         
         self.showMsg(CurrSettingsMsg)         

         self.waitForDistance()
            
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DELLA DISTANZA DI OFFSET (da step = 0)
      elif self.step == 1: # 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
                  if self.offSet < 0:
                     value = QadMsg.translate("Command_OFFSET", "Through")
                  else:
                     value = self.offSet
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False
            else:
               value = self.getPointMapTool().point
         else: # il punto arriva come parametro della funzione
            value = msg
         
         if type(value) == unicode:
            if value == QadMsg.translate("Command_OFFSET", "Through") or value == "Through":
               self.offSet = -1
               self.getPointMapTool().offSet = self.offSet
               QadVariables.set(QadMsg.translate("Environment variables", "OFFSETDIST"), self.offSet)
               QadVariables.save()               
               # si appresta ad attendere la selezione di un oggetto
               self.waitForObjectSel()
            elif value == QadMsg.translate("Command_OFFSET", "Erase") or value == "Erase":
               keyWords = QadMsg.translate("QAD", "Yes") + "/" + \
                          QadMsg.translate("QAD", "No")
              
               if self.eraseEntity == True:
                  default = QadMsg.translate("QAD", "Yes")
               else: 
                  default = QadMsg.translate("QAD", "No")
               prompt = QadMsg.translate("Command_OFFSET", "Erase source object after offsetting ? [{0}] <{1}>: ").format(keyWords, default)
                   
               englishKeyWords = "Yes" + "/" + "No"
               keyWords += "_" + englishKeyWords
               # si appresta ad attendere enter o una parola chiave
               # msg, inputType, default, keyWords, nessun controllo
               self.waitFor(prompt, \
                            QadInputTypeEnum.KEYWORDS, \
                            default, \
                            keyWords, QadInputModeEnum.NONE)
               self.step = 5
            elif value == QadMsg.translate("Command_OFFSET", "Multiple") or value == "Multiple":
               self.multi = True
               self.waitForBasePt()                         
         elif type(value) == QgsPoint: # se é stato inserito il primo punto per il calcolo della distanza
            self.firstPt.set(value.x(), value.y())
            # imposto il map tool
            self.getPointMapTool().firstPt = self.firstPt           
            self.getPointMapTool().setMode(Qad_offset_maptool_ModeEnum.FIRST_OFFSET_PT_KNOWN_ASK_FOR_SECOND_PT)
            # si appresta ad attendere un punto
            self.waitForPoint(QadMsg.translate("Command_OFFSET", "Specify second point: "))
            self.step = 6
         elif type(value) == float:
            self.offSet = value
            self.getPointMapTool().offSet = self.offSet
            QadVariables.set(QadMsg.translate("Environment variables", "OFFSETDIST"), self.offSet)
            QadVariables.save()
            # si appresta ad attendere la selezione di un oggetto
            self.waitForObjectSel()
         
         return False 

      #=========================================================================
      # RISPOSTA ALLA SELEZIONE DI UN OGGETTO
      elif self.step == 2:
         entity = None
         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 = QadMsg.translate("Command_OFFSET", "Exit")
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False
            else:
               entity = self.getPointMapTool().entity
               value = self.getPointMapTool().point
         else: # il punto arriva come parametro della funzione
            value = msg
         
         if type(value) == unicode:
            if value == QadMsg.translate("Command_OFFSET", "Exit") or value == "Exit":
               self.offsetGeoms(currLayer)
               return True
            elif value == QadMsg.translate("Command_OFFSET", "Undo") or value == "Undo":
               self.undoGeomsInCache()
               # si appresta ad attendere la selezione di un oggetto
               self.waitForObjectSel()
         elif type(value) == QgsPoint: # se é stato selezionato un punto
            if entity is not None and entity.isInitialized(): # se é stata selezionata una entità
               self.entity.set(entity.layer, entity.featureId)
               self.getPointMapTool().layer = self.entity.layer
               # trasformo la geometria nel crs del canvas per lavorare con coordinate piane xy
               geom = self.layerToMapCoordinates(entity.layer, entity.getGeometry())

               # ritorna una tupla (<The squared cartesian distance>,
               #                    <minDistPoint>
               #                    <afterVertex>
               #                    <leftOf>)
               dummy = qad_utils.closestSegmentWithContext(value, geom)
               if dummy[2] is not None:
                  # ritorna la sotto-geometria al vertice <atVertex> e la sua posizione nella geometria (0-based)
                  # la posizione é espressa con una lista (<index ogg. princ> [<index ogg. sec.>])
                  self.subGeom = qad_utils.getSubGeomAtVertex(geom, dummy[2])[0]
                  self.subGeomSelectedPt = QgsPoint(value)
                  
                  self.getPointMapTool().subGeom = self.subGeom
                  if self.offSet < 0: # richiesta di punto di passaggio
                     self.waitForPassagePt()
                  else:  # richiesta la parte dell'oggetto
                     self.waitForSidePt()
            else:
               # si appresta ad attendere la selezione di un oggetto
               self.waitForObjectSel()

         return False

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DI UN PUNTO PER STABILIRE LA PARTE DI OFFSET  (da step = 2)
      elif self.step == 3:
         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.multi == False: # default = esci                     
                     self.offsetGeoms(currLayer)
                     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 value is None: # oggetto successivo
            # si appresta ad attendere la selezione di un oggetto
            self.waitForObjectSel()
         else:
            if type(value) == unicode:
               if value == QadMsg.translate("Command_OFFSET", "Exit") or value == "Exit":
                  self.offsetGeoms(currLayer)
                  return True # fine comando
               elif value == QadMsg.translate("Command_OFFSET", "Multiple") or value == "Multiple":
                  self.multi = True
                  self.waitForSidePt()               
               elif value == QadMsg.translate("Command_OFFSET", "Undo") or value == "Undo":
                  self.undoGeomsInCache()               
                  # si appresta ad attendere la selezione di un oggetto
                  self.waitForObjectSel()
               elif value == QadMsg.translate("Command_OFFSET", "Segment") or value == "Segment":
                  self.OnlySegment = True   
                  linearObject = qad_utils.QadLinearObject()
                  if linearObject.setByClosestSegmentOfGeom(self.subGeomSelectedPt, self.subGeom) == True:
                     self.subGeom = QgsGeometry.fromPolyline(linearObject.asPolyline())
                     self.getPointMapTool().subGeom = self.subGeom
                  
                  self.waitForSidePt()                  
            elif type(value) == QgsPoint: # se é stato selezionato un punto            
               self.addFeatureCache(value) 
               if self.multi == False:
                  # si appresta ad attendere la selezione di un oggetto
                  self.waitForObjectSel()
               else:
                  # richiesta la parte dell'oggetto
                  self.waitForSidePt()

         return False

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DI UN PUNTO DI PASSAGGIO DI OFFSET  (da step = 2)
      elif self.step == 4:
         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.multi == False: # default = esci                     
                     self.offsetGeoms(currLayer)
                     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 value is None: # oggetto successivo
            # si appresta ad attendere la selezione di un oggetto
            self.waitForObjectSel()
         else:
            if type(value) == unicode:
               if value == QadMsg.translate("Command_OFFSET", "Exit") or value == "Exit":
                  self.offsetGeoms(currLayer)
                  return True # fine comando
               elif value == QadMsg.translate("Command_OFFSET", "Multiple") or value == "Multiple":
                  self.multi = True
                  self.waitForPassagePt()     
               elif value == QadMsg.translate("Command_OFFSET", "Undo") or value == "Undo":
                  self.undoGeomsInCache()               
                  # si appresta ad attendere la selezione di un oggetto
                  self.waitForObjectSel()
               elif value == QadMsg.translate("Command_OFFSET", "Segment") or value == "Segment":
                  self.OnlySegment = True                  
                  linearObject = qad_utils.QadLinearObject()
                  if linearObject.setByClosestSegmentOfGeom(self.subGeomSelectedPt, self.subGeom) == True:
                     self.subGeom = QgsGeometry.fromPolyline(linearObject.asPolyline())
                     self.getPointMapTool().subGeom = self.subGeom
                  
                  self.waitForPassagePt()     
            elif type(value) == QgsPoint: # se é stato selezionato un punto            
               self.addFeatureCache(value)       
               if self.multi == False:
                  # si appresta ad attendere la selezione di un oggetto
                  self.waitForObjectSel()
               else:
                  # richiesta di punto di passaggio
                  self.waitForPassagePt()

         return False

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DI CANCELLAZIONE OGGETTO SORGENTE (da step = 1)
      elif self.step == 5: # 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().rightButton == True: # se usato il tasto destro del mouse
               value = QadMsg.translate("QAD", "No")   
            else:
               self.setMapTool(self.getPointMapTool()) # riattivo il maptool
               return False
         else: # il valore arriva come parametro della funzione
            value = msg

         if type(value) == unicode:
            if value == QadMsg.translate("QAD", "Yes") or value == "Yes":
               self.eraseEntity = True
               self.waitForDistance()
            elif value == QadMsg.translate("QAD", "No") or value == "No":
               self.eraseEntity = False
               self.waitForDistance()
         
         return False

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA SECONDO PUNTO PER LUNGHEZZA OFFSET (da step = 1)
      elif self.step == 6: # 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 value == self.firstPt:
            self.showMsg(QadMsg.translate("QAD", "\nThe value must be positive and not zero."))
            # si appresta ad attendere un punto
            self.waitForPoint(QadMsg.translate("Command_OFFSET", "Specify second point: "))
            return False
               
         self.offSet = qad_utils.getDistance(self.firstPt, value)
         self.getPointMapTool().offSet = self.offSet
         QadVariables.set(QadMsg.translate("Environment variables", "OFFSETDIST"), self.offSet)
         QadVariables.save()
         # si appresta ad attendere la selezione di un oggetto
         self.waitForObjectSel()

         return False class QadEXTENDCommandClass(QadCommandClass):

   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadEXTENDCommandClass(self.plugIn)
   
   def getName(self):
      return QadMsg.translate("Command_list", "EXTEND")

   def getEnglishName(self):
      return "EXTEND"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runEXTENDCommand)

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/extend.png")

   def getNote(self):
      # impostare le note esplicative del comando
      return QadMsg.translate("Command_EXTEND", "Extends (or trims) objects to meet the edges of other objects.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      self.SSGetClass = QadSSGetClass(plugIn)
      self.PLINECommand = None      
      self.RECTANGLECommand = None
      self.entitySet = QadEntitySet() # entità da estendere o tagliare
      self.limitEntitySet = QadEntitySet() # entità che fanno da limiti
      self.edgeMode = QadVariables.get(QadMsg.translate("Environment variables", "EDGEMODE"))
      self.defaultValue = None # usato per gestire il tasto dx del mouse
      self.nOperationsToUndo = 0

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


   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      if self.step == 3: # quando si é in fase di disegno linea
         return self.PLINECommand.getPointMapTool(drawMode)
      elif self.step == 4: # quando si é in fase di disegno rettangolo 
         return self.RECTANGLECommand.getPointMapTool(drawMode)      
      else:
         return QadCommandClass.getPointMapTool(self, drawMode)


   def getCurrentContextualMenu(self):
      if self.step == 3: # quando si é in fase di disegno linea
         return self.PLINECommand.getCurrentContextualMenu()
      elif self.step == 4: # quando si é in fase di disegno rettangolo 
         return self.RECTANGLECommand.getCurrentContextualMenu()
      else:
         return self.contextualMenu


   #============================================================================
   # extendFeatures
   #============================================================================
   def extendFeatures(self, geom, toExtend):
      # geom è in map coordinates
      tolerance2ApproxCurve = QadVariables.get(QadMsg.translate("Environment variables", "TOLERANCE2APPROXCURVE"))
      LineTempLayer = None
      self.plugIn.beginEditCommand("Feature extended" if toExtend else "Feature trimmed", \
                                   self.entitySet.getLayerList())
      
      for layerEntitySet in self.entitySet.layerEntitySetList:
         layer = layerEntitySet.layer
                              
         for featureId in layerEntitySet.featureIds:
            f = qad_utils.getFeatureById(layer, featureId)
            if f is None:
               continue
            # trasformo la geometria nel crs del canvas per lavorare con coordinate piane xy
            f_geom = self.layerToMapCoordinates(layer, f.geometry())
            
            if geom.type() == QGis.Point:               
               # ritorna una tupla (<The squared cartesian distance>,
               #                    <minDistPoint>
               #                    <afterVertex>
               #                    <leftOf>)
               dummy = qad_utils.closestSegmentWithContext(geom.asPoint(), f_geom)
               if dummy[1] is not None:
                  intPts = [dummy[1]]
            else:
               intPts = qad_utils.getIntersectionPoints(geom, f_geom)
               
            for intPt in intPts:               
               if toExtend:
                  newGeom = qad_utils.extendQgsGeometry(self.plugIn.canvas.mapSettings().destinationCrs(), f_geom, intPt, \
                                                        self.limitEntitySet, self.edgeMode, \
                                                        tolerance2ApproxCurve)
                  if newGeom is not None:
                     # aggiorno la feature con la geometria estesa
                     extendedFeature = QgsFeature(f)
                     # trasformo la geometria nel crs del layer
                     extendedFeature.setGeometry(self.mapToLayerCoordinates(layer, newGeom))
                     # plugIn, layer, feature, refresh, check_validity
                     if qad_layer.updateFeatureToLayer(self.plugIn, layer, extendedFeature, False, False) == False:
                        self.plugIn.destroyEditCommand()
                        return
               else: # trim
                  result = qad_utils.trimQgsGeometry(self.plugIn.canvas.mapSettings().destinationCrs(), f_geom, intPt, \
                                                     self.limitEntitySet, self.edgeMode, \
                                                     tolerance2ApproxCurve)                  
                  if result is not None:
                     line1 = result[0]
                     line2 = result[1]
                     atSubGeom = result[2]
                     if layer.geometryType() == QGis.Line:
                        updGeom = qad_utils.setSubGeom(f_geom, line1, atSubGeom)
                        if updGeom is None:
                           self.plugIn.destroyEditCommand()
                           return
                        trimmedFeature1 = QgsFeature(f)
                        # trasformo la geometria nel crs del layer
                        trimmedFeature1.setGeometry(self.mapToLayerCoordinates(layer, updGeom))
                        # plugIn, layer, feature, refresh, check_validity
                        if qad_layer.updateFeatureToLayer(self.plugIn, layer, trimmedFeature1, False, False) == False:
                           self.plugIn.destroyEditCommand()
                           return
                        if line2 is not None:
                           trimmedFeature2 = QgsFeature(f)      
                           # trasformo la geometria nel crs del layer
                           trimmedFeature2.setGeometry(self.mapToLayerCoordinates(layer, line2))
                           # plugIn, layer, feature, coordTransform, refresh, check_validity
                           if qad_layer.addFeatureToLayer(self.plugIn, layer, trimmedFeature2, None, False, False) == False:
                              self.plugIn.destroyEditCommand()
                              return
                        
                     else:
                        # aggiungo le linee nei layer temporanei di QAD
                        if LineTempLayer is None:
                           LineTempLayer = qad_layer.createQADTempLayer(self.plugIn, QGis.Line)
                           self.plugIn.addLayerToLastEditCommand("Feature trimmed", LineTempLayer)
                        
                        lineGeoms = [line1]
                        if line2 is not None:
                           lineGeoms.append(line2)

                        # trasformo la geometria in quella dei layer temporanei
                        # plugIn, pointGeoms, lineGeoms, polygonGeoms, coord, refresh
                        if qad_layer.addGeometriesToQADTempLayers(self.plugIn, None, lineGeoms, None, None, False) == False:
                           self.plugIn.destroyEditCommand()
                           return
                                                      
                        updGeom = qad_utils.delSubGeom(f_geom, atSubGeom)
                        
                        if updGeom is None or updGeom.isGeosEmpty(): # da cancellare
                           # plugIn, layer, feature id, refresh
                           if qad_layer.deleteFeatureToLayer(self.plugIn, layer, f.id(), False) == False:
                              self.plugIn.destroyEditCommand()
                              return
                        else:
                           trimmedFeature1 = QgsFeature(f)
                           # trasformo la geometria nel crs del layer
                           trimmedFeature1.setGeometry(self.mapToLayerCoordinates(layer, updGeom))
                           # plugIn, layer, feature, refresh, check_validity
                           if qad_layer.updateFeatureToLayer(self.plugIn, layer, trimmedFeature1, False, False) == False:
                              self.plugIn.destroyEditCommand()
                              return

      self.plugIn.endEditCommand()
      self.nOperationsToUndo = self.nOperationsToUndo + 1
                                                      
      
   #============================================================================
   # waitForObjectSel
   #============================================================================
   def waitForObjectSel(self):      
      self.step = 2      
      # imposto il map tool
      self.getPointMapTool().setSelectionMode(QadGetPointSelectionModeEnum.ENTITY_SELECTION_DYNAMIC)
      # solo layer lineari editabili che non appartengano a quote
      layerList = []
      for layer in qad_utils.getVisibleVectorLayers(self.plugIn.canvas): # Tutti i layer vettoriali visibili
         if layer.geometryType() == QGis.Line and layer.isEditable():
            if len(QadDimStyles.getDimListByLayer(layer)) == 0:
               layerList.append(layer)
      
      self.getPointMapTool().layersToCheck = layerList
      self.getPointMapTool().setDrawMode(QadGetPointDrawModeEnum.NONE)
      self.getPointMapTool().onlyEditableLayers = True
      
      keyWords = QadMsg.translate("Command_EXTEND", "Fence") + "/" + \
                 QadMsg.translate("Command_EXTEND", "Crossing") + "/" + \
                 QadMsg.translate("Command_EXTEND", "Edge") + "/" + \
                 QadMsg.translate("Command_EXTEND", "Undo")
      prompt = QadMsg.translate("Command_EXTEND", "Select the object to extend or shift-select to trim or [{0}]: ").format(keyWords)
      
      englishKeyWords = "Fence" + "/" + "Crossing" + "/" + "Edge" + "/" + "Undo"
      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)      


   #============================================================================
   # 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 LIMITI
      if self.step == 0: # inizio del comando
         CurrSettingsMsg = QadMsg.translate("QAD", "\nCurrent settings: ")
         if self.edgeMode == 0: # 0 = nessuna estensione
            CurrSettingsMsg = CurrSettingsMsg + QadMsg.translate("Command_EXTEND", "Edge = No extend")
         else:
            CurrSettingsMsg = CurrSettingsMsg + QadMsg.translate("Command_EXTEND", "Edge = Extend")
                  
         self.showMsg(CurrSettingsMsg)         
         self.showMsg(QadMsg.translate("Command_EXTEND", "\nSelect extension limits..."))
         
         if self.SSGetClass.run(msgMapTool, msg) == True:
            # selezione terminata
            self.step = 1
            return self.run(msgMapTool, msg)        
      
      #=========================================================================
      # RISPOSTA ALLA SELEZIONE OGGETTI LIMITI
      elif self.step == 1:
         self.limitEntitySet.set(self.SSGetClass.entitySet)
         
         if self.limitEntitySet.count() == 0:
            return True # fine comando

         # si appresta ad attendere la selezione degli oggetti da estendere/tagliare
         self.waitForObjectSel()
         return False
      
      #=========================================================================
      # RISPOSTA ALLA SELEZIONE OGGETTI DA ESTENDERE
      elif self.step == 2:
         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
            else:
               value = self.getPointMapTool().point
         else: # il punto arriva come parametro della funzione
            value = msg

         if type(value) == unicode:
            if value == QadMsg.translate("Command_EXTEND", "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 = 3
               return False               
            elif value == QadMsg.translate("Command_EXTEND", "Crossing") or value == "Crossing":
               # Seleziona tutti gli oggetti che intersecano un rettangolo                                  
               self.RECTANGLECommand = QadRECTANGLECommandClass(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.RECTANGLECommand.virtualCmd = True   
               self.RECTANGLECommand.run(msgMapTool, msg)
               self.step = 4
               return False               
            elif value == QadMsg.translate("Command_EXTEND", "Edge") or value == "Edge":
               # Per estendere un oggetto usando anche le estensioni degli oggetti di riferimento
               # vedi variabile EDGEMODE
               keyWords = QadMsg.translate("Command_EXTEND", "Extend") + "/" + \
                          QadMsg.translate("Command_EXTEND", "No extend")                                              

               if self.edgeMode == 0: # 0 = nessuna estensione
                  self.defaultValue = QadMsg.translate("Command_EXTEND", "No extend")
               else: 
                  self.defaultValue = QadMsg.translate("Command_EXTEND", "Extend")                   
               prompt = QadMsg.translate("Command_EXTEND", "Specify an extension mode [{0}] <{1}>: ").format(keyWords, self.defaultValue)
                   
               englishKeyWords = "Extend" + "/" + "No extend"
               keyWords += "_" + englishKeyWords
               # si appresta ad attendere enter o una parola chiave         
               # msg, inputType, default, keyWords, nessun controllo
               self.waitFor(prompt, \
                            QadInputTypeEnum.KEYWORDS, \
                            self.defaultValue, \
                            keyWords, QadInputModeEnum.NONE)
               self.step = 5               
               return False               
            elif value == QadMsg.translate("Command_EXTEND", "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."))
         elif type(value) == QgsPoint: # se é stato selezionato un punto
            self.entitySet.clear()
            if self.getPointMapTool().entity.isInitialized():
               self.entitySet.addEntity(self.getPointMapTool().entity)
               ToExtend = True if self.getPointMapTool().shiftKey == False else False
               self.extendFeatures(QgsGeometry.fromPoint(value), ToExtend)
            else:
               # cerco se ci sono entità nel punto indicato considerando
               # solo layer lineari editabili che non appartengano a quote
               layerList = []
               for layer in qad_utils.getVisibleVectorLayers(self.plugIn.canvas): # Tutti i layer vettoriali visibili
                  if layer.geometryType() == QGis.Line and layer.isEditable():
                     if len(QadDimStyles.getDimListByLayer(layer)) == 0:
                        layerList.append(layer)
                                     
               result = qad_utils.getEntSel(self.getPointMapTool().toCanvasCoordinates(value), \
                                            self.getPointMapTool(), \
                                            QadVariables.get(QadMsg.translate("Environment variables", "PICKBOX")), \
                                            layerList)
               if result is not None:
                  feature = result[0]
                  layer = result[1]
                  point = result[2]
                  self.entitySet.addEntity(QadEntity().set(layer, feature.id()))
                  self.extendFeatures(QgsGeometry.fromPoint(point), True)
         else:
            return True # fine comando
         
         # si appresta ad attendere la selezione degli oggetti da estendere/tagliare
         self.waitForObjectSel()
                                          
         return False 

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA PUNTO PER MODALITA' INTERCETTA (da step = 2)
      elif self.step == 3: # dopo aver atteso un punto si riavvia il comando
         if self.PLINECommand.run(msgMapTool, msg) == True:
            if len(self.PLINECommand.vertices) > 1:
               if msgMapTool == True: # se la polilinea arriva da una selezione grafica
                  ToExtend = True if self.getPointMapTool().shiftKey == False else False
               else:
                  ToExtend = True

               # cerco tutte le geometrie passanti per la polilinea considerando
               # solo layer lineari editabili che non appartengano a quote
               layerList = []
               for layer in qad_utils.getVisibleVectorLayers(self.plugIn.canvas): # Tutti i layer vettoriali visibili
                  if layer.geometryType() == QGis.Line and layer.isEditable():
                     if len(QadDimStyles.getDimListByLayer(layer)) == 0:
                        layerList.append(layer)
               
               self.entitySet = qad_utils.getSelSet("F", self.getPointMapTool(), self.PLINECommand.vertices, \
                                                    layerList)            
               self.extendFeatures(QgsGeometry.fromPolyline(self.PLINECommand.vertices), ToExtend)
            del self.PLINECommand
            self.PLINECommand = None

            # si appresta ad attendere la selezione degli oggetti da estendere/tagliare
            self.waitForObjectSel()                                 
            self.getPointMapTool().refreshSnapType() # aggiorno lo snapType che può essere variato dal maptool di pline                     
         return False

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA PUNTO PER MODALITA' INTERSECA (da step = 2)
      elif self.step == 4: # dopo aver atteso un punto si riavvia il comando
         if self.RECTANGLECommand.run(msgMapTool, msg) == True:            
            if len(self.RECTANGLECommand.vertices) > 1:
               if msgMapTool == True: # se la polilinea arriva da una selezione grafica
                  ToExtend = True if self.getPointMapTool().shiftKey == False else False
               else:
                  ToExtend = True
               
               # cerco tutte le geometrie passanti per il rettangolo considerando
               # solo layer lineari editabili che non appartengano a quote
               layerList = []
               for layer in qad_utils.getVisibleVectorLayers(self.plugIn.canvas): # Tutti i layer vettoriali visibili
                  if layer.geometryType() == QGis.Line and layer.isEditable():
                     if len(QadDimStyles.getDimListByLayer(layer)) == 0:
                        layerList.append(layer)
                        
               self.entitySet = qad_utils.getSelSet("F", self.getPointMapTool(), self.RECTANGLECommand.vertices, \
                                                    layerList)            
               self.extendFeatures(QgsGeometry.fromPolyline(self.RECTANGLECommand.vertices), ToExtend)
            del self.RECTANGLECommand
            self.RECTANGLECommand = None

            # si appresta ad attendere la selezione degli oggetti da estendere/tagliare
            self.waitForObjectSel()                                 
            self.getPointMapTool().refreshSnapType() # aggiorno lo snapType che può essere variato dal maptool di rectangle                   
         return False

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DI TIPO DI ESTENSIONE (da step = 2)
      elif self.step == 5: # 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().rightButton == True: # se usato il tasto destro del mouse
               value = self.defaultValue 
            else:
               self.setMapTool(self.getPointMapTool()) # riattivo il maptool
               return False
         else: # il valore arriva come parametro della funzione
            value = msg

         if type(value) == unicode:
            if value == QadMsg.translate("Command_EXTEND", "No extend") or value == "No extend":
               self.edgeMode = 0
               QadVariables.set(QadMsg.translate("Environment variables", "EDGEMODE"), self.edgeMode)
               QadVariables.save()
               # si appresta ad attendere la selezione degli oggetti da estendere/tagliare
               self.waitForObjectSel()
            elif value == QadMsg.translate("Command_EXTEND", "Extend") or value == "Extend":
               self.edgeMode = 1
               QadVariables.set(QadMsg.translate("Environment variables", "EDGEMODE"), self.edgeMode)
               QadVariables.save()
               # si appresta ad attendere la selezione degli oggetti da estendere/tagliare
               self.waitForObjectSel()
         
         return False class QadTRIMCommandClass(QadCommandClass):

   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadTRIMCommandClass(self.plugIn)
   
   def getName(self):
      return QadMsg.translate("Command_list", "TRIM")

   def getEnglishName(self):
      return "TRIM"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runTRIMCommand)

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/trim.png")

   def getNote(self):
      # impostare le note esplicative del comando
      return QadMsg.translate("Command_TRIM", "Trims (or extends) objects to meet the edges of other objects.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      self.SSGetClass = QadSSGetClass(plugIn)
      self.PLINECommand = None      
      self.RECTANGLECommand = None
      self.entitySet = QadEntitySet() # entità da tagliare o estendere
      self.limitEntitySet = QadEntitySet() # entità che fanno da limiti
      self.edgeMode = QadVariables.get(QadMsg.translate("Environment variables", "EDGEMODE"))
      self.defaultValue = None # usato per gestire il tasto dx del mouse
      self.nOperationsToUndo = 0

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


   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      if self.step == 3: # quando si é in fase di disegno linea
         return self.PLINECommand.getPointMapTool(drawMode)
      elif self.step == 4: # quando si é in fase di disegno rettangolo 
         return self.RECTANGLECommand.getPointMapTool(drawMode)      
      else:
         return QadCommandClass.getPointMapTool(self, drawMode)


   def getCurrentContextualMenu(self):
      if self.step == 3: # quando si é in fase di disegno linea
         return self.PLINECommand.getCurrentContextualMenu()
      elif self.step == 4: # quando si é in fase di disegno rettangolo 
         return self.RECTANGLECommand.getCurrentContextualMenu()
      else:
         return self.contextualMenu


   #============================================================================
   # trimFeatures
   #============================================================================
   def trimFeatures(self, geom, toExtend):
      # geom è in map coordinates
      tolerance2ApproxCurve = QadVariables.get(QadMsg.translate("Environment variables", "TOLERANCE2APPROXCURVE"))
      LineTempLayer = None
      self.plugIn.beginEditCommand("Feature extended" if toExtend else "Feature trimmed", \
                                   self.entitySet.getLayerList())
      
      for layerEntitySet in self.entitySet.layerEntitySetList:
         layer = layerEntitySet.layer

         for featureId in layerEntitySet.featureIds:
            f = qad_utils.getFeatureById(layer, featureId)
            if f is None:
               continue
            # trasformo la geometria nel crs del canvas per lavorare con coordinate piane xy
            f_geom = self.layerToMapCoordinates(layer, f.geometry())
            
            if geom.type() == QGis.Point:
               # ritorna una tupla (<The squared cartesian distance>,
               #                    <minDistPoint>
               #                    <afterVertex>
               #                    <leftOf>)
               dummy = qad_utils.closestSegmentWithContext(geom.asPoint(), f_geom)
               if dummy[1] is not None:
                  intPts = [dummy[1]]
            else:
               intPts = qad_utils.getIntersectionPoints(geom, f_geom)
               
            for intPt in intPts:               
               if toExtend:
                  newGeom = qad_utils.extendQgsGeometry(self.plugIn.canvas.mapSettings().destinationCrs(), f_geom, intPt, \
                                                        self.limitEntitySet, self.edgeMode, \
                                                        tolerance2ApproxCurve)
                  if newGeom is not None:
                     # aggiorno la feature con la geometria estesa
                     extendedFeature = QgsFeature(f)
                     # trasformo la geometria nel crs del layer
                     extendedFeature.setGeometry(self.mapToLayerCoordinates(layer, newGeom))
                     # plugIn, layer, feature, refresh, check_validity
                     if qad_layer.updateFeatureToLayer(self.plugIn, layer, extendedFeature, False, False) == False:
                        self.plugIn.destroyEditCommand()
                        return
               else: # trim
                  result = qad_utils.trimQgsGeometry(self.plugIn.canvas.mapSettings().destinationCrs(), f_geom, intPt, \
                                                     self.limitEntitySet, self.edgeMode, \
                                                     tolerance2ApproxCurve)                  
                  if result is not None:
                     line1 = result[0]
                     line2 = result[1]
                     atSubGeom = result[2]
                     if layer.geometryType() == QGis.Line:
                        updGeom = qad_utils.setSubGeom(f_geom, line1, atSubGeom)
                        if updGeom is None:
                           self.plugIn.destroyEditCommand()
                           return
                        trimmedFeature1 = QgsFeature(f)
                        # trasformo la geometria nel crs del layer
                        trimmedFeature1.setGeometry(self.mapToLayerCoordinates(layer, updGeom))
                        # plugIn, layer, feature, refresh, check_validity
                        if qad_layer.updateFeatureToLayer(self.plugIn, layer, trimmedFeature1, False, False) == False:
                           self.plugIn.destroyEditCommand()
                           return
                        if line2 is not None:
                           trimmedFeature2 = QgsFeature(f)      
                           # trasformo la geometria nel crs del layer
                           trimmedFeature2.setGeometry(self.mapToLayerCoordinates(layer, line2))
                           # plugIn, layer, feature, coordTransform, refresh, check_validity
                           if qad_layer.addFeatureToLayer(self.plugIn, layer, trimmedFeature2, None, False, False) == False:
                              self.plugIn.destroyEditCommand()
                              return                        
                     else:
                        # aggiungo le linee nei layer temporanei di QAD
                        if LineTempLayer is None:
                           LineTempLayer = qad_layer.createQADTempLayer(self.plugIn, QGis.Line)
                           self.plugIn.addLayerToLastEditCommand("Feature trimmed", LineTempLayer)
                        
                        lineGeoms = [line1]
                        if line2 is not None:
                           lineGeoms.append(line2)

                        # trasformo la geometria in quella dei layer temporanei
                        # plugIn, pointGeoms, lineGeoms, polygonGeoms, coord, refresh
                        if qad_layer.addGeometriesToQADTempLayers(self.plugIn, None, lineGeoms, None, None, False) == False:
                           self.plugIn.destroyEditCommand()
                           return
                                                      
                        updGeom = qad_utils.delSubGeom(f_geom, atSubGeom)
                        
                        if updGeom is None or updGeom.isGeosEmpty(): # da cancellare
                           # plugIn, layer, feature id, refresh
                           if qad_layer.deleteFeatureToLayer(self.plugIn, layer, f.id(), False) == False:
                              self.plugIn.destroyEditCommand()
                              return
                        else:
                           trimmedFeature1 = QgsFeature(f)
                           # trasformo la geometria nel crs del layer
                           trimmedFeature1.setGeometry(self.mapToLayerCoordinates(layer, updGeom))
                           # plugIn, layer, feature, refresh, check_validity
                           if qad_layer.updateFeatureToLayer(self.plugIn, layer, trimmedFeature1, False, False) == False:
                              self.plugIn.destroyEditCommand()
                              return

      self.plugIn.endEditCommand()
      self.nOperationsToUndo = self.nOperationsToUndo + 1
                                                      
      
   #============================================================================
   # waitForObjectSel
   #============================================================================
   def waitForObjectSel(self):      
      self.step = 2      
      # imposto il map tool
      self.getPointMapTool().setSelectionMode(QadGetPointSelectionModeEnum.ENTITY_SELECTION_DYNAMIC)
      # solo layer lineari editabili che non appartengano a quote
      layerList = []
      for layer in qad_utils.getVisibleVectorLayers(self.plugIn.canvas): # Tutti i layer vettoriali visibili
         if layer.geometryType() == QGis.Line and layer.isEditable():
            if len(QadDimStyles.getDimListByLayer(layer)) == 0:
               layerList.append(layer)
            
      self.getPointMapTool().layersToCheck = layerList
      self.getPointMapTool().setDrawMode(QadGetPointDrawModeEnum.NONE)
      self.getPointMapTool().onlyEditableLayers = True
      
      keyWords = QadMsg.translate("Command_TRIM", "Fence") + "/" + \
                 QadMsg.translate("Command_TRIM", "Crossing") + "/" + \
                 QadMsg.translate("Command_TRIM", "Edge") + "/" + \
                 QadMsg.translate("Command_TRIM", "Undo")      
      prompt = QadMsg.translate("Command_TRIM", "Select the object to trim or shift-select to extend or [{0}]: ").format(keyWords)                        
      
      englishKeyWords = "Fence" + "/" + "Crossing" + "/" + "Edge" + "/" + "Undo"
      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)      


   #============================================================================
   # 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 LIMITI
      if self.step == 0: # inizio del comando
         CurrSettingsMsg = QadMsg.translate("QAD", "\nCurrent settings: ")
         if self.edgeMode == 0: # 0 = nessuna estensione
            CurrSettingsMsg = CurrSettingsMsg + QadMsg.translate("Command_TRIM", "Edge = No extend")
         else:
            CurrSettingsMsg = CurrSettingsMsg + QadMsg.translate("Command_TRIM", "Edge = Extend")
                  
         self.showMsg(CurrSettingsMsg)         
         self.showMsg(QadMsg.translate("Command_TRIM", "\nSelect trim limits..."))
         
         if self.SSGetClass.run(msgMapTool, msg) == True:
            # selezione terminata
            self.step = 1
            return self.run(msgMapTool, msg)        
      
      #=========================================================================
      # RISPOSTA ALLA SELEZIONE OGGETTI LIMITI
      elif self.step == 1:
         self.limitEntitySet.set(self.SSGetClass.entitySet)
         
         if self.limitEntitySet.count() == 0:
            return True # fine comando

         # si appresta ad attendere la selezione degli oggetti da estendere/tagliare
         self.waitForObjectSel()
         return False
      
      #=========================================================================
      # RISPOSTA ALLA SELEZIONE OGGETTI DA ESTENDERE
      elif self.step == 2:
         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
            else:
               value = self.getPointMapTool().point
         else: # il punto arriva come parametro della funzione
            value = msg

         if type(value) == unicode:
            if value == QadMsg.translate("Command_TRIM", "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 = 3
               return False               
            elif value == QadMsg.translate("Command_TRIM", "Crossing") or value == "Crossing":
               # Seleziona tutti gli oggetti che intersecano un rettangolo                                  
               self.RECTANGLECommand = QadRECTANGLECommandClass(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.RECTANGLECommand.virtualCmd = True   
               self.RECTANGLECommand.run(msgMapTool, msg)
               self.step = 4
               return False               
            elif value == QadMsg.translate("Command_TRIM", "Edge") or value == "Edge":
               # Per estendere un oggetto usando anche le estensioni degli oggetti di riferimento
               # vedi variabile EDGEMODE
               keyWords = QadMsg.translate("Command_TRIM", "Extend") + "/" + \
                          QadMsg.translate("Command_TRIM", "No extend")
               if self.edgeMode == 0: # 0 = nessuna estensione
                  self.defaultValue = QadMsg.translate("Command_TRIM", "No")
               else: 
                  self.defaultValue = QadMsg.translate("Command_TRIM", "Extend")
               prompt = QadMsg.translate("Command_TRIM", "Specify an extension mode [{0}] <{1}>: ").format(keyWords, self.defaultValue)                        
                   
               englishKeyWords = "Extend" + "/" + "No extend"
               keyWords += "_" + englishKeyWords
               # si appresta ad attendere enter o una parola chiave         
               # msg, inputType, default, keyWords, nessun controllo
               self.waitFor(prompt, \
                            QadInputTypeEnum.KEYWORDS, \
                            self.defaultValue, \
                            keyWords, QadInputModeEnum.NONE)
               self.step = 5               
               return False               
            elif value == QadMsg.translate("Command_TRIM", "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."))
         elif type(value) == QgsPoint: # se é stato selezionato un punto
            self.entitySet.clear()
            if self.getPointMapTool().entity.isInitialized():
               self.entitySet.addEntity(self.getPointMapTool().entity)
               ToExtend = True if self.getPointMapTool().shiftKey == True else False
               self.trimFeatures(QgsGeometry.fromPoint(value), ToExtend)
            else:
               # cerco se ci sono entità nel punto indicato considerando
               # solo layer lineari editabili che non appartengano a quote
               layerList = []
               for layer in qad_utils.getVisibleVectorLayers(self.plugIn.canvas): # Tutti i layer vettoriali visibili
                  if layer.geometryType() == QGis.Line and layer.isEditable():
                     if len(QadDimStyles.getDimListByLayer(layer)) == 0:
                        layerList.append(layer)
               
               result = qad_utils.getEntSel(self.getPointMapTool().toCanvasCoordinates(value),
                                            self.getPointMapTool(), \
                                            QadVariables.get(QadMsg.translate("Environment variables", "PICKBOX")), \
                                            layerList)
               if result is not None:
                  feature = result[0]
                  layer = result[1]
                  point = result[2]
                  self.entitySet.addEntity(QadEntity().set(layer, feature.id()))
                  self.trimFeatures(QgsGeometry.fromPoint(point), False)
         else:
            return True # fine comando
         
         # si appresta ad attendere la selezione degli oggetti da estendere/tagliare
         self.waitForObjectSel()
                                          
         return False 

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA PUNTO PER MODALITA' INTERCETTA (da step = 2)
      elif self.step == 3: # dopo aver atteso un punto si riavvia il comando
         if self.PLINECommand.run(msgMapTool, msg) == True:
            if len(self.PLINECommand.vertices) > 1:
               if msgMapTool == True: # se la polilinea arriva da una selezione grafica
                  ToExtend = True if self.getPointMapTool().shiftKey == True else False
               else:
                  ToExtend = False

               # cerco tutte le geometrie passanti per la polilinea saltando i layer punto e poligono
               # e considerando solo layer editabili       
               self.entitySet = qad_utils.getSelSet("F", self.getPointMapTool(), self.PLINECommand.vertices, \
                                                    None, False, True, False, \
                                                    True)            
               self.trimFeatures(QgsGeometry.fromPolyline(self.PLINECommand.vertices), ToExtend)
            del self.PLINECommand
            self.PLINECommand = None

            # si appresta ad attendere la selezione degli oggetti da estendere/tagliare
            self.waitForObjectSel()
            self.getPointMapTool().refreshSnapType() # aggiorno lo snapType che può essere variato dal maptool di pline                     
                                             
         return False

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA PUNTO PER MODALITA' INTERSECA (da step = 2)
      elif self.step == 4: # dopo aver atteso un punto si riavvia il comando
         if self.RECTANGLECommand.run(msgMapTool, msg) == True:            
            if len(self.RECTANGLECommand.vertices) > 1:
               if msgMapTool == True: # se la polilinea arriva da una selezione grafica
                  ToExtend = True if self.getPointMapTool().shiftKey == True else False
               else:
                  ToExtend = False
               
               # cerco tutte le geometrie passanti per la polilinea saltando i layer punto e poligono
               # e considerando solo layer editabili       
               self.entitySet = qad_utils.getSelSet("F", self.getPointMapTool(), self.RECTANGLECommand.vertices, \
                                                    None, False, True, False, \
                                                    True)            
               self.trimFeatures(QgsGeometry.fromPolyline(self.RECTANGLECommand.vertices), ToExtend)
            del self.RECTANGLECommand
            self.RECTANGLECommand = None

            # si appresta ad attendere la selezione degli oggetti da estendere/tagliare
            self.waitForObjectSel()                                 
            self.getPointMapTool().refreshSnapType() # aggiorno lo snapType che può essere variato dal maptool di rectangle                     
         return False

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DI TIPO DI ESTENSIONE (da step = 2)
      elif self.step == 5: # 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().rightButton == True: # se usato il tasto destro del mouse
               value = self.defaultValue 
            else:
               self.setMapTool(self.getPointMapTool()) # riattivo il maptool
               return False
         else: # il valore arriva come parametro della funzione
            value = msg

         if type(value) == unicode:
            if value == QadMsg.translate("Command_TRIM", "No") or value == "No":
               self.edgeMode = 0
               QadVariables.set(QadMsg.translate("Environment variables", "EDGEMODE"), self.edgeMode)
               QadVariables.save()
               # si appresta ad attendere la selezione degli oggetti da estendere/tagliare
               self.waitForObjectSel()
            elif value == QadMsg.translate("Command_TRIM", "Extend") or value == "Extend":
               self.edgeMode = 1
               QadVariables.set(QadMsg.translate("Environment variables", "EDGEMODE"), self.edgeMode)
               QadVariables.save()
               # si appresta ad attendere la selezione degli oggetti da estendere/tagliare
               self.waitForObjectSel()
         
         return False class QadRECTANGLECommandClass(QadCommandClass):

   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadRECTANGLECommandClass(self.plugIn)
   
   def getName(self):
      return QadMsg.translate("Command_list", "RECTANGLE")

   def getEnglishName(self):
      return "RECTANGLE"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runRECTANGLECommand)

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/rectangle.png")

   def getNote(self):
      # impostare le note esplicative del comando
      return QadMsg.translate("Command_RECTANGLE", "Creates a rectangle.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      # se questo flag = True il comando serve all'interno di un altro comando per disegnare un rettangolo
      # che non verrà salvato su un layer
      self.virtualCmd = False
      self.firstCorner = None
      self.gapType = 0 # 0 = Angoli retti; 1 = Raccorda i segmenti; 2 = Cima i segmenti
      self.gapValue1 = 0 # se gapType = 1 -> raggio di curvatura; se gapType = 2 -> prima distanza di cimatura
      self.gapValue2 = 0 # se gapType = 2 -> seconda distanza di cimatura
      self.area = 100
      self.dim1 = 10
      self.rot = 0
      self.vertices = []
      
      self.GetDistClass = None
      self.GetAngleClass = None
      self.defaultValue = None # usato per gestire il tasto dx del mouse

   def __del__(self):
      QadCommandClass.__del__(self)
      if self.GetDistClass is not None:
         del self.GetDistClass
      if self.GetAngleClass is not None:
         del self.GetAngleClass


   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      # quando si é in fase di richiesta distanza
      if self.step == 3 or self.step == 4 or self.step == 5 or \
         self.step == 8 or self.step == 9 or self.step == 10 or self.step == 11:
         return self.GetDistClass.getPointMapTool()
      # quando si é in fase di richiesta rotazione
      elif self.step == 13:
         return self.GetAngleClass.getPointMapTool()
      else:
         if (self.plugIn is not None):
            if self.PointMapTool is None:
               self.PointMapTool = Qad_rectangle_maptool(self.plugIn)
            return self.PointMapTool
         else:
            return None       


   def getCurrentContextualMenu(self):
      # quando si é in fase di richiesta distanza
      if self.step == 3 or self.step == 4 or self.step == 5 or \
         self.step == 8 or self.step == 9 or self.step == 10 or self.step == 11:
         return self.GetDistClass.getCurrentContextualMenu()
      # quando si é in fase di richiesta rotazione
      elif self.step == 13:
         return self.GetAngleClass.getCurrentContextualMenu()
      else:
         return self.contextualMenu

      
   def addRectangleToLayer(self, layer):
      if layer.geometryType() == QGis.Line:
         qad_layer.addLineToLayer(self.plugIn, layer, self.vertices)
      elif layer.geometryType() == QGis.Polygon:                          
         qad_layer.addPolygonToLayer(self.plugIn, layer, self.vertices)
      
         
   #============================================================================
   # WaitForFirstCorner
   #============================================================================
   def WaitForFirstCorner(self):
      self.step = 1         
      self.getPointMapTool().setMode(Qad_rectangle_maptool_ModeEnum.NONE_KNOWN_ASK_FOR_FIRST_CORNER)
      
      keyWords = QadMsg.translate("Command_RECTANGLE", "Chamfer") + "/" + \
                 QadMsg.translate("Command_RECTANGLE", "Fillet")
      prompt = QadMsg.translate("Command_RECTANGLE", "Specify first corner or [{0}]: ").format(keyWords)

      englishKeyWords = "Chamfer" + "/" + "Fillet"
      keyWords += "_" + englishKeyWords     
      # si appresta ad attendere un punto o enter
      #                        msg, inputType,              default, keyWords, nessun controllo         
      self.waitFor(prompt, \
                   QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS, \
                   None, keyWords, QadInputModeEnum.NONE)
         
   #============================================================================
   # WaitForSecondCorner
   #============================================================================
   def WaitForSecondCorner(self, layer):
      self.step = 2
      self.getPointMapTool().rot = self.rot
      self.getPointMapTool().gapType = self.gapType
      self.getPointMapTool().gapValue1 = self.gapValue1
      self.getPointMapTool().gapValue2 = self.gapValue2
      self.getPointMapTool().setMode(Qad_rectangle_maptool_ModeEnum.FIRST_CORNER_KNOWN_ASK_FOR_SECOND_CORNER)
      if layer is not None:
         self.getPointMapTool().geomType = layer.geometryType()
      
      keyWords = QadMsg.translate("Command_RECTANGLE", "Area") + "/" + \
                 QadMsg.translate("Command_RECTANGLE", "Dimensions") + "/" + \
                 QadMsg.translate("Command_RECTANGLE", "Rotation")
      prompt = QadMsg.translate("Command_RECTANGLE", "Specify other corner or [{0}]: ").format(keyWords)

      englishKeyWords = "Area" + "/" + "Dimensions" + "/" + "Rotation"
      keyWords += "_" + englishKeyWords
      # si appresta ad attendere un punto o enter
      #                        msg, inputType,              default, keyWords, nessun controllo         
      self.waitFor(prompt, \
                   QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS, \
                   None, keyWords, QadInputModeEnum.NONE)
         
   #============================================================================
   # 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

      currLayer = None
      if self.virtualCmd == False: # se si vuole veramente salvare la polylinea in un layer   
         # il layer corrente deve essere editabile e di tipo linea o poligono
         currLayer, errMsg = qad_layer.getCurrLayerEditable(self.plugIn.canvas, [QGis.Line, QGis.Polygon])
         if currLayer is None:
            self.showErr(errMsg)
            return True # fine comando
      
      #=========================================================================
      # RICHIESTA PRIMO PUNTO 
      if self.step == 0: # inizio del comando
         self.WaitForFirstCorner()         
         return False

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL PRIMO PUNTO DEL RETTANGOLO (da step = 0)
      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
               if self.getPointMapTool().rightButton == True: # se usato il tasto destro del mouse
                  self.showMsg(QadMsg.translate("Command_RECTANGLE", "Window not correct."))
                  self.WaitForFirstCorner()
                  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) == unicode:
            if value == QadMsg.translate("Command_RECTANGLE", "Chamfer") or value == "Chamfer":
               if self.GetDistClass is not None:
                  del self.GetDistClass
               self.GetDistClass = QadGetDistClass(self.plugIn)
               prompt = QadMsg.translate("Command_RECTANGLE", "Specify first chamfer distance for rectangle <{0}>: ")
               self.GetDistClass.msg = prompt.format(str(self.gapValue1))
               self.GetDistClass.dist = self.gapValue1
               self.GetDistClass.inputMode = QadInputModeEnum.NOT_NEGATIVE
               self.step = 4
               self.GetDistClass.run(msgMapTool, msg)     
            elif value == QadMsg.translate("Command_RECTANGLE", "Fillet") or value == "Fillet":
               if self.GetDistClass is not None:
                  del self.GetDistClass
               self.GetDistClass = QadGetDistClass(self.plugIn)
               prompt = QadMsg.translate("Command_RECTANGLE", "Specify rectangle fillet radius <{0}>: ")
               self.GetDistClass.msg = prompt.format(str(self.gapValue1))
               self.GetDistClass.dist = self.gapValue1
               self.GetDistClass.inputMode = QadInputModeEnum.NOT_NEGATIVE
               self.step = 3
               self.GetDistClass.run(msgMapTool, msg)     
         elif type(value) == QgsPoint:
            self.firstCorner = value
            self.getPointMapTool().firstCorner = self.firstCorner
            self.WaitForSecondCorner(currLayer)         

         return False # continua


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL SECONDO PUNTO DEL RETTANGOLO (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_RECTANGLE", "Window not correct."))
                  self.WaitForSecondCorner(currLayer)
                  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) == unicode:
            if value == QadMsg.translate("Command_RECTANGLE", "Area") or value == "Area":
               msg = QadMsg.translate("Command_RECTANGLE", "Enter rectangle area in current units <{0}>: ")
               # si appresta ad attendere un numero reale         
               # msg, inputType, default, keyWords, valori positivi
               self.waitFor(msg.format(str(self.area)), QadInputTypeEnum.FLOAT, \
                            self.area, "", \
                            QadInputModeEnum.NOT_ZERO | QadInputModeEnum.NOT_NEGATIVE)
               self.getPointMapTool().setMode(Qad_rectangle_maptool_ModeEnum.NONE_KNOWN_ASK_FOR_FIRST_CORNER)
                  
               self.step = 6
            elif value == QadMsg.translate("Command_RECTANGLE", "Dimensions") or value == "Dimensions":
               if self.GetDistClass is not None:
                  del self.GetDistClass
               self.GetDistClass = QadGetDistClass(self.plugIn)
               prompt = QadMsg.translate("Command_RECTANGLE", "Specify length for rectangle <{0}>: ")
               self.GetDistClass.msg = prompt.format(str(self.dim1))
               self.GetDistClass.dist = self.dim1
               self.step = 10
               self.GetDistClass.run(msgMapTool, msg)              
            elif value == QadMsg.translate("Command_RECTANGLE", "Rotation") or value == "Rotation":
               keyWords = QadMsg.translate("Command_RECTANGLE", "Points")
               self.defaultValue = self.rot
               prompt = QadMsg.translate("Command_RECTANGLE", "Specify rotation angle or [{0}] <{1}>: ").format(keyWords, str(qad_utils.toDegrees(self.rot)))
               
               englishKeyWords = "Points"
               keyWords += "_" + englishKeyWords
               # si appresta ad attendere un punto o un numero reale         
               # msg, inputType, default, keyWords, valori non nulli
               self.waitFor(prompt, \
                            QadInputTypeEnum.POINT2D | QadInputTypeEnum.FLOAT | QadInputTypeEnum.KEYWORDS, \
                            self.rot, keyWords)
               self.getPointMapTool().setMode(Qad_rectangle_maptool_ModeEnum.NONE_KNOWN_ASK_FOR_FIRST_CORNER)
               
               self.step = 12
         elif type(value) == QgsPoint:
            self.vertices.extend(qad_utils.getRectByCorners(self.firstCorner, value, self.rot, \
                                                            self.gapType, self.gapValue1, self.gapValue2))

            if self.virtualCmd == False: # se si vuole veramente salvare i buffer in un layer
               self.addRectangleToLayer(currLayer)
            return True       

         return False # continua

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA RAGGIO DI CURVATURA (da step = 1)
      elif self.step == 3:
         if self.GetDistClass.run(msgMapTool, msg) == True:
            if self.GetDistClass.dist is not None:
               self.gapValue1 = self.GetDistClass.dist
               if self.gapValue1 == 0:
                  self.gapType = 0 # 0 = Angoli retti
               else:
                  self.gapType = 1 # 1 = Raccorda i segmenti

            self.WaitForFirstCorner()
            self.getPointMapTool().refreshSnapType() # aggiorno lo snapType che può essere variato dal maptool di distanza                     
         return False # fine comando

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA PRIMA DISTANZA DI CIMATURA (da step = 1)
      elif self.step == 4:
         if self.GetDistClass.run(msgMapTool, msg) == True:
            if self.GetDistClass.dist is not None:
               self.gapValue1 = self.GetDistClass.dist
               
               if self.GetDistClass is not None:
                  del self.GetDistClass
               self.GetDistClass = QadGetDistClass(self.plugIn)
               prompt = QadMsg.translate("Command_RECTANGLE", "Specify second chamfer distance for rectangle <{0}>: ")
               self.GetDistClass.msg = prompt.format(str(self.gapValue2))
               self.GetDistClass.dist = self.gapValue2
               self.GetDistClass.inputMode = QadInputModeEnum.NOT_NEGATIVE
               self.step = 5
               self.GetDistClass.run(msgMapTool, msg)  
            else:   
               self.WaitForFirstCorner()
               self.getPointMapTool().refreshSnapType() # aggiorno lo snapType che può essere variato dal maptool di distanza                                 
         return False # fine comando
 
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA SECONDA DISTANZA DI CIMATURA (da step = 1)
      elif self.step == 5:
         if self.GetDistClass.run(msgMapTool, msg) == True:
            if self.GetDistClass.dist is not None:
               self.gapValue2 = self.GetDistClass.dist               
               if self.gapValue1 == 0 or self.gapValue2 == 0:
                  self.gapType = 0 # 0 = Angoli retti
               else:
                  self.gapType = 2 # 2 = Cima i segmenti
                                   
            self.WaitForFirstCorner()
            self.getPointMapTool().refreshSnapType() # aggiorno lo snapType che può essere variato dal maptool di distanza                     
         return False # fine comando
 
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA AREA RETTANGOLO (da step = 2)
      elif self.step == 6: # dopo aver atteso un punto si riavvia il comando
         keyWords = QadMsg.translate("Command_RECTANGLE", "Length") + "/" + \
                    QadMsg.translate("Command_RECTANGLE", "Width")
         englishKeyWords = "Length" + "/" + "Width"
         
         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.defaultValue = QadMsg.translate("Command_RECTANGLE", "Length")
                  prompt = QadMsg.translate("Command_RECTANGLE", "Calcolate the rectangle dimensions based on [{0}] <{1}>: ").format(keyWords, self.defaultValue)
                        
                  keyWords += "_" + englishKeyWords
                  # si appresta ad attendere una parola chiave         
                  # msg, inputType, default, keyWords, valori positivi
                  self.waitFor(prompt, QadInputTypeEnum.KEYWORDS, \
                               self.defaultValue, \
                               keyWords, QadInputModeEnum.NONE)                  
                  
                  self.step = 7
                  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) == float: # é stata inserita l'area
            self.area = value
            self.defaultValue = QadMsg.translate("Command_RECTANGLE", "Length")
            prompt = QadMsg.translate("Command_RECTANGLE", "Calcolate the rectangle dimensions based on [{0}] <{1}>: ").format(keyWords, self.defaultValue)
                  
            keyWords += "_" + englishKeyWords
            # si appresta ad attendere una parola chiave         
            # msg, inputType, default, keyWords, valori positivi
            self.waitFor(prompt, QadInputTypeEnum.KEYWORDS, \
                         self.defaultValue, \
                         keyWords, QadInputModeEnum.NONE)
            self.step = 7
         return False
            
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DELLA MODALITA' (LUNGHEZZA / LARGHEZZA) DATA L'AREA (da step = 6)
      elif self.step == 7: # 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
                  value = self.defaultValue
                  return True # fine comando
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False
            else:
               return False
         else: # il punto arriva come parametro della funzione
            value = msg

         if value == QadMsg.translate("Command_RECTANGLE", "Length") or value == "Length":
            if self.GetDistClass is not None:
               del self.GetDistClass
            self.GetDistClass = QadGetDistClass(self.plugIn)
            prompt = QadMsg.translate("Command_RECTANGLE", "Enter length for rectangle <{0}>: ")
            self.GetDistClass.msg = prompt.format(str(self.dim1))
            self.GetDistClass.dist = self.dim1
            self.step = 8
            self.GetDistClass.run(msgMapTool, msg)              
         elif value == QadMsg.translate("Command_RECTANGLE", "Width") or value == "Width":
            if self.GetDistClass is not None:
               del self.GetDistClass
            self.GetDistClass = QadGetDistClass(self.plugIn)
            prompt = QadMsg.translate("Command_RECTANGLE", "Enter width for rectangle <{0}>: ")
            self.GetDistClass.msg = prompt.format(str(self.dim1))
            self.GetDistClass.dist = self.dim1
            self.step = 9
            self.GetDistClass.run(msgMapTool, msg)              
            
         return False

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA LUNGHEZZA RETTANGOLO DATA L'AREA (da step = 7)
      elif self.step == 8:
         if self.GetDistClass.run(msgMapTool, msg) == True:
            if self.GetDistClass.dist is not None:
					self.vertices.extend(qad_utils.getRectByAreaAndLength(self.firstCorner, self.area, self.GetDistClass.dist, \
																							self.rot, self.gapType, self.gapValue1, self.gapValue2))	
					if self.virtualCmd == False: # se si vuole veramente salvare i buffer in un layer
						self.addRectangleToLayer(currLayer)
					return True # fine comando		
         return False
            
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA LARGHEZZA RETTANGOLO DATA L'AREA (da step = 7)
      elif self.step == 9:
         if self.GetDistClass.run(msgMapTool, msg) == True:
            if self.GetDistClass.dist is not None:
					self.vertices.extend(qad_utils.getRectByAreaAndWidth(self.firstCorner, self.area, self.GetDistClass.dist, \
																							self.rot, self.gapType, self.gapValue1, self.gapValue2))	
					if self.virtualCmd == False: # se si vuole veramente salvare i buffer in un layer
						self.addRectangleToLayer(currLayer)
					return True # fine comando		
         return False
            
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA LUNGHEZZA RETTANGOLO (da step = 2)
      elif self.step == 10:
         if self.GetDistClass.run(msgMapTool, msg) == True:
            if self.GetDistClass.dist is not None:
               self.dim1 = self.GetDistClass.dist

            if self.GetDistClass is not None:
               del self.GetDistClass
            self.GetDistClass = QadGetDistClass(self.plugIn)
            prompt = QadMsg.translate("Command_RECTANGLE", "Enter width for rectangle <{0}>: ")
            self.GetDistClass.msg = prompt.format(str(self.dim1))
            self.GetDistClass.dist = self.dim1
            self.step = 11
            self.GetDistClass.run(msgMapTool, msg)              
                         
         return False

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA LARGHEZZA RETTANGOLO (da step = 10)
      elif self.step == 11:
         if self.GetDistClass.run(msgMapTool, msg) == True:
            if self.GetDistClass.dist is not None:
               self.vertices.extend(qad_utils.getRectByCornerAndDims(self.firstCorner, self.dim1, self.GetDistClass.dist, \
                                                                     self.rot, self.gapType, self.gapValue1, self.gapValue2))   
               if self.virtualCmd == False: # se si vuole veramente salvare i buffer in un layer
                  self.addRectangleToLayer(currLayer)
               return True # fine comando      
         return False

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA ROTAZIONE RETTANGOLO (da step = 2)
      elif self.step == 12: # 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
                  value = self.defaultValue
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False
            else:
               value = self.getPointMapTool().point
         else: # il punto arriva come parametro della funzione
            value = msg

         if type(value) == unicode:
            if value == QadMsg.translate("Command_RECTANGLE", "Points") or value == "Points":
               # si appresta ad attendere l'angolo di rotazione                      
               if self.GetAngleClass is not None:
                  del self.GetAngleClass                  
               self.GetAngleClass = QadGetAngleClass(self.plugIn)
               self.GetAngleClass.msg = QadMsg.translate("Command_RECTANGLE", "Specify first point: ")
               self.GetAngleClass.angle = self.rot
               self.step = 13
               self.GetAngleClass.run(msgMapTool, msg)               
         elif type(value) == QgsPoint:
            self.rot = qad_utils.getAngleBy2Pts(self.firstCorner, value)
            self.WaitForSecondCorner(currLayer)
         elif type(value) == float:
            self.rot = qad_utils.toRadians(value)
            self.WaitForSecondCorner(currLayer)
            
         return False # continua
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA ROTAZIONE RETTANGOLO (da step = 12)
      elif self.step == 13:
         if self.GetAngleClass.run(msgMapTool, msg) == True:
            if self.GetAngleClass.angle is not None:
               self.rot = self.GetAngleClass.angle
               self.plugIn.setLastRot(self.rot)
               self.WaitForSecondCorner(currLayer)
               self.getPointMapTool().refreshSnapType() # aggiorno lo snapType che può essere variato dal maptool di rotazione                      class QadMIRRORCommandClass(QadCommandClass):
   
   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadMIRRORCommandClass(self.plugIn)
   
   def getName(self):
      return QadMsg.translate("Command_list", "MIRROR")

   def getEnglishName(self):
      return "MIRROR"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runMIRRORCommand)

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/mirror.png")

   def getNote(self):
      # impostare le note esplicative del comando      
      return QadMsg.translate("Command_MIRROR", "Creates a mirrored copy of selected objects.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      self.SSGetClass = QadSSGetClass(plugIn)
      self.SSGetClass.onlyEditableLayers = True
      self.entitySet = QadEntitySet()
      self.firstMirrorPt = QgsPoint()
      self.secondMirrorPt = QgsPoint()
      self.copyFeatures = True

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


   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      if self.step == 0: # quando si é in fase di selezione entità
         return self.SSGetClass.getPointMapTool()
      else:
         if (self.plugIn is not None):
            if self.PointMapTool is None:
               self.PointMapTool = Qad_mirror_maptool(self.plugIn)
            return self.PointMapTool
         else:
            return None


   def getCurrentContextualMenu(self):
      if self.step == 0: # quando si é in fase di selezione entità
         return self.SSGetClass.getCurrentContextualMenu()
      else:
         return self.contextualMenu


   #============================================================================
   # scale
   #============================================================================
   def mirror(self, f, pt1, pt2, rotFldName, layerEntitySet, entitySet, dimEntity):
      
      if dimEntity is None:
         # scalo la feature e la rimuovo da entitySet (é la prima)
         f.setGeometry(qad_utils.mirrorQgsGeometry(f.geometry(), 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.copyFeatures == False:
            # plugIn, layer, feature, refresh, check_validity
            if qad_layer.updateFeatureToLayer(self.plugIn, layerEntitySet.layer, f, False, False) == False:
               self.plugIn.destroyEditCommand()
               return False
         else:             
            # plugIn, layer, features, coordTransform, refresh, check_validity
            if qad_layer.addFeatureToLayer(self.plugIn, layerEntitySet.layer, f, None, False, False) == False:
               self.plugIn.destroyEditCommand()
               return False

         del layerEntitySet.featureIds[0]
      else:
         # scalo la quota e la rimuovo da entitySet
         mirrorAngle = qad_utils.getAngleBy2Pts(pt1, pt2)
         dimEntitySet = dimEntity.getEntitySet()
         if self.copyFeatures == False:
            if dimEntity.deleteToLayers(self.plugIn) == False:
               return False
         newDimEntity = QadDimEntity(dimEntity) # la copio
         newDimEntity.mirror(pt1, mirrorAngle)
         if newDimEntity.addToLayers(self.plugIn) == False:
            return False             
         entitySet.subtract(dimEntitySet)


   #============================================================================
   # mirrorGeoms
   #============================================================================
   def mirrorGeoms(self):      
      # copio entitySet
      entitySet = QadEntitySet(self.entitySet)

      self.plugIn.beginEditCommand("Feature mirrored", self.entitySet.getLayerList())

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

         transformedBasePt = self.mapToLayerCoordinates(layer, self.firstMirrorPt)
         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)
         
         while len(layerEntitySet.featureIds) > 0:
            featureId = layerEntitySet.featureIds[0]
            f = layerEntitySet.getFeature(featureId)

            entity = QadEntity()
            entity.set(layer, featureId)
            # verifico se l'entità appartiene ad uno stile di quotatura
            dimStyle, dimId = QadDimStyles.getDimIdByEntity(entity)

            if dimStyle is not None:
               dimEntity = QadDimEntity()
               if dimEntity.initByDimId(dimStyle, dimId) == False:
                  dimEntity = None
            else:
               dimEntity = None

            if self.mirror(f, transformedBasePt, transformedNewPt, rotFldName, layerEntitySet, entitySet, dimEntity) == False:  
               self.plugIn.destroyEditCommand()
               return

      self.plugIn.endEditCommand()
   

   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.SSGetClass.run(msgMapTool, msg) == True:
            # selezione terminata
            self.step = 1
            self.getPointMapTool().refreshSnapType() # aggiorno lo snapType che può essere variato dal maptool di selezione entità                    
            return self.run(msgMapTool, msg)
      
      #=========================================================================
      # SPECCHIA OGGETTI
      elif self.step == 1:
         self.entitySet.set(self.SSGetClass.entitySet)
         
         if self.entitySet.count() == 0:
            return True # fine comando

         # imposto il map tool
         self.getPointMapTool().entitySet.set(self.entitySet)
         self.getPointMapTool().setMode(Qad_mirror_maptool_ModeEnum.NONE_KNOWN_ASK_FOR_FIRST_PT)                                
   
         # si appresta ad attendere un punto
         self.waitForPoint(QadMsg.translate("Command_MIRROR", "Specify first point of mirror line: "))
         self.step = 2      
         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
                  # si appresta ad attendere un punto
                  self.waitForPoint(QadMsg.translate("Command_MIRROR", "Specify first point of mirror line: "))
                  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

         self.firstMirrorPt.set(value.x(), value.y())

         # imposto il map tool
         self.getPointMapTool().firstMirrorPt = self.firstMirrorPt
         self.getPointMapTool().setMode(Qad_mirror_maptool_ModeEnum.FIRST_PT_KNOWN_ASK_FOR_SECOND_PT)                                
         
         # si appresta ad attendere un punto
         self.waitForPoint(QadMsg.translate("Command_MIRROR", "Specify second point of mirror line: "))
         self.step = 3
         
         return False 
         
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA SECONDO PUNTO PER SPECCHIO (da step = 2)
      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
                  # si appresta ad attendere un punto
                  self.waitForPoint(QadMsg.translate("Command_MIRROR", "Specify second point of mirror line: "))
               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 qad_utils.ptNear(self.firstMirrorPt, value):
            self.showMsg(QadMsg.translate("Command_MIRROR", "\nThe points must be different."))
            # si appresta ad attendere un punto
            self.waitForPoint(QadMsg.translate("Command_MIRROR", "Specify second point of mirror line: "))
            return False
         
         self.secondMirrorPt.set(value.x(), value.y())
         
         keyWords = QadMsg.translate("QAD", "Yes") + "/" + \
                    QadMsg.translate("QAD", "No")                                       
         if self.copyFeatures == False:
            default = QadMsg.translate("QAD", "Yes")
         else: 
            default = QadMsg.translate("QAD", "No")
         prompt = QadMsg.translate("Command_MIRROR", "Erase source objects ? [{0}] <{1}>: ").format(keyWords, default)
             
         englishKeyWords = "Yes" + "/" + "No"
         keyWords += "_" + englishKeyWords
         # si appresta ad attendere enter o una parola chiave         
         # msg, inputType, default, keyWords, nessun controllo
         self.waitFor(prompt, \
                      QadInputTypeEnum.KEYWORDS, \
                      default, \
                      keyWords, QadInputModeEnum.NONE)
         self.getPointMapTool().setMode(Qad_mirror_maptool_ModeEnum.NONE_KNOWN_ASK_FOR_FIRST_PT)                                         
         self.step = 4

         return False
            

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DI CANCELLAZIONE OGGETTO SORGENTE (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().rightButton == True: # se usato il tasto destro del mouse
               value = QadMsg.translate("QAD", "No")   
            else:
               self.setMapTool(self.getPointMapTool()) # riattivo il maptool
               return False
         else: # il valore arriva come parametro della funzione
            value = msg

         if type(value) == unicode:
            if value == QadMsg.translate("QAD", "Yes") or value == "Yes":
               self.copyFeatures = False
            elif value == QadMsg.translate("QAD", "No") or value == "No":
               self.copyFeatures = True
                     
            self.mirrorGeoms()
            return True # fine comando

         return False class QadUNDOCommandClass(QadCommandClass):

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

   def getName(self):
      return QadMsg.translate("Command_list", "UNDO")

   def getEnglishName(self):
      return "UNDO"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runUNDOCommand)

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/undo.png")
   
   def getNote(self):
      # impostare le note esplicative del comando      
      return QadMsg.translate("Command_UNDO", "Reverses the effect of commands.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
         
   def run(self, msgMapTool = False, msg = None):
      self.isValidPreviousInput = True # per gestire il comando anche in macro

      if self.step == 0: # inizio del comando
         keyWords = QadMsg.translate("Command_UNDO", "BEgin") + "/" + \
                    QadMsg.translate("Command_UNDO", "End") + "/" + \
                    QadMsg.translate("Command_UNDO", "Mark") + "/" + \
                    QadMsg.translate("Command_UNDO", "Back")
         default = 1
         prompt = QadMsg.translate("Command_UNDO", "Enter the number of operations to undo or [{0}] <{1}>: ").format(keyWords, str(default))
         
         englishKeyWords = "BEgin" + "/" + "End" + "/" + "Mark" + "/" + "Back"
         keyWords += "_" + englishKeyWords
         # si appresta ad attendere un numero intero positivo o enter o una parola chiave         
         # msg, inputType, default, keyWords, valori positivi
         self.waitFor(prompt, \
                      QadInputTypeEnum.INT | QadInputTypeEnum.KEYWORDS, \
                      default, \
                      keyWords, QadInputModeEnum.NOT_ZERO | QadInputModeEnum.NOT_NEGATIVE)      
         self.step = 1
         return False
   
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA NUMERO INTERO (da step = 0)
      elif self.step == 1: # 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
                  self.plugIn.undoEditCommand()
                  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) == unicode:
            if value == QadMsg.translate("Command_UNDO", "BEgin") or value == "BEgin":
               self.plugIn.insertBeginGroup()
            elif value == QadMsg.translate("Command_UNDO", "End") or value == "End":
               if self.plugIn.insertEndGroup() == False:
                  self.showMsg(QadMsg.translate("Command_UNDO", "\nNo open group."))
            elif value == QadMsg.translate("Command_UNDO", "Mark") or value == "Mark":
               if self.plugIn.insertBookmark() == False:
                  self.showMsg(QadMsg.translate("Command_UNDO", "\nA mark can't be inserted into a group."))
            elif value == QadMsg.translate("Command_UNDO", "Back") or value == "Back":
               if self.plugIn.getPrevBookmarkPos() == -1: # non ci sono bookmark precedenti
                  keyWords = QadMsg.translate("QAD", "Yes") + "/" + \
                             QadMsg.translate("QAD", "No")
                  default = QadMsg.translate("QAD", "Yes")
                  prompt = QadMsg.translate("Command_UNDO", "This will undo everything. OK ? <{0}>: ").format(default)
                  
                  englishKeyWords = "Yes" + "/" + "No"
                  keyWords += "_" + englishKeyWords
                  # si appresta ad attendere enter o una parola chiave         
                  # msg, inputType, default, keyWords, nessun controllo
                  self.waitFor(prompt, \
                               QadInputTypeEnum.KEYWORDS, \
                               default, \
                               keyWords, QadInputModeEnum.NONE)
                  self.step = 2
                  return False                                       
               else:
                  self.plugIn.undoUntilBookmark()
         elif type(value) == int:
            self.plugIn.undoEditCommand(value)

         return True
         
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DI ANNULLARE TUTTO (da step = 1)
      elif self.step == 2: # dopo aver atteso 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
                  self.plugIn.undoUntilBookmark()
                  self.showMsg(QadMsg.translate("Command_UNDO", "All has been undone."))
                  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) == unicode:
            if value == QadMsg.translate("QAD", "Yes") or value == "Yes":
               self.showMsg(QadMsg.translate("Command_UNDO", "All has been undone."))
               self.plugIn.undoUntilBookmark()

         return True # fine comando class QadREDOCommandClass(QadCommandClass):
   
   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadREDOCommandClass(self.plugIn)

   def getName(self):
      return QadMsg.translate("Command_list", "REDO")

   def getEnglishName(self):
      return "REDO"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runREDOCommand)

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/redo.png")
   
   def getNote(self):
      # impostare le note esplicative del comando      
      return QadMsg.translate("Command_UNDO", "Reverses the effects of previous UNDO.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
         
   def run(self, msgMapTool = False, msg = None):
      self.plugIn.redoEditCommand()
      return True    class QadINSERTCommandClass(QadCommandClass):

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

   def getName(self):
      return QadMsg.translate("Command_list", "INSERT")

   def getEnglishName(self):
      return "INSERT"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runINSERTCommand)
   
   def getIcon(self):
      return QIcon(":/plugins/qad/icons/insert.png")

   def getNote(self):
      # impostare le note esplicative del comando
      return QadMsg.translate("Command_INSERT", "Insert a symbol.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      self.insPt = None
      self.scale = self.plugIn.lastScale
      self.rot = self.plugIn.lastRot
      self.GetDistClass = None
      self.GetAngleClass = None

   def __del__(self):
      QadCommandClass.__del__(self)
      if self.GetDistClass is not None:
         del self.GetDistClass
      if self.GetAngleClass is not None:
         del self.GetAngleClass


   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      # quando si é in fase di richiesta distanza (scala)
      if self.step == 2:
         return self.GetDistClass.getPointMapTool()
      # quando si é in fase di richiesta rotazione
      elif self.step == 3:
         return self.GetAngleClass.getPointMapTool()
      else:
         return QadCommandClass.getPointMapTool(self, drawMode)


   def getCurrentContextualMenu(self):
      # quando si é in fase di richiesta distanza (scala)
      if self.step == 2:
         return self.GetDistClass.getCurrentContextualMenu()
      # quando si é in fase di richiesta rotazione
      elif self.step == 3:
         return self.GetAngleClass.getCurrentContextualMenu()
      else:
         return self.contextualMenu


   def addFeature(self, layer):
      transformedPoint = self.mapToLayerCoordinates(layer, self.insPt)
      g = QgsGeometry.fromPoint(transformedPoint)
      f = QgsFeature()
      f.setGeometry(g)
      # Add attribute fields to feature.
      fields = layer.pendingFields()
      f.setFields(fields)
      
      # assegno i valori di default
      provider = layer.dataProvider()
      for field in fields.toList():
         i = fields.indexFromName(field.name())
         f[field.name()] = provider.defaultValue(i)
      
      # se la scala dipende da un campo 
      scaleFldName = qad_layer.get_symbolScaleFieldName(layer)
      if len(scaleFldName) > 0:
         f.setAttribute(scaleFldName, self.scale)
      
      # se la rotazione dipende da un campo
      rotFldName = qad_layer.get_symbolRotationFieldName(layer)
      if len(rotFldName) > 0:
         f.setAttribute(rotFldName, qad_utils.toDegrees(self.rot))
      
      return qad_layer.addFeatureToLayer(self.plugIn, layer, f)               
      
      
   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
      
      currLayer, errMsg = qad_layer.getCurrLayerEditable(self.plugIn.canvas, QGis.Point)
      if currLayer is None:
         self.showErr(errMsg)
         return True # fine comando

      if qad_layer.isSymbolLayer(currLayer) == False:
         errMsg = QadMsg.translate("QAD", "\nCurrent layer is not a symbol layer.")
         errMsg = errMsg + QadMsg.translate("QAD", "\nA symbol layer is a vector punctual layer without label.\n")
         self.showErr(errMsg)         
         return True # fine comando

               
      #=========================================================================
      # RICHIESTA PUNTO DI INSERIMENTO
      if self.step == 0: # inizio del comando
         self.waitForPoint() # si appresta ad attendere un punto
         self.step = self.step + 1
         return False
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA PUNTO DI INSERIMENTO
      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
               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

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

         self.insPt = QgsPoint(pt)
         self.plugIn.setLastPoint(self.insPt)
         
         # se la scala dipende da un campo 
         scaleFldName = qad_layer.get_symbolScaleFieldName(currLayer)
         if len(scaleFldName) > 0:
            # si appresta ad attendere la scala                      
            self.GetDistClass = QadGetDistClass(self.plugIn)
            prompt = QadMsg.translate("Command_INSERT", "Specify the symbol scale <{0}>: ")
            self.GetDistClass.msg = prompt.format(str(self.scale))
            self.GetDistClass.dist = self.scale
            self.GetDistClass.inputMode = QadInputModeEnum.NOT_NEGATIVE | QadInputModeEnum.NOT_ZERO
            self.GetDistClass.startPt = self.insPt
            self.step = 2
            self.GetDistClass.run(msgMapTool, msg)
            return False
         else: 
            # se la rotazione dipende da un campo 
            rotFldName = qad_layer.get_symbolRotationFieldName(currLayer)
            if len(rotFldName) > 0:
               if self.GetAngleClass is not None:
                  del self.GetAngleClass                  
               # si appresta ad attendere l'angolo di rotazione                      
               self.GetAngleClass = QadGetAngleClass(self.plugIn)
               prompt = QadMsg.translate("Command_INSERT", "Specify the symbol rotation <{0}>: ")
               self.GetAngleClass.msg = prompt.format(str(qad_utils.toDegrees(self.rot)))
               self.GetAngleClass.angle = self.rot
               self.GetAngleClass.startPt = self.insPt               
               self.step = 3
               self.GetAngleClass.run(msgMapTool, msg)               
               return False
            else:
               self.addFeature(currLayer)

         return True
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA SCALA (da step = 1)
      elif self.step == 2:
         if self.GetDistClass.run(msgMapTool, msg) == True:
            if self.GetDistClass.dist is not None:
               self.scale = self.GetDistClass.dist
               self.plugIn.setLastScale(self.scale)
               del self.GetDistClass
               self.GetDistClass = None
                
               # se la rotazione dipende da un campo 
               rotFldName = qad_layer.get_symbolRotationFieldName(currLayer)
               if len(rotFldName) > 0:
                  if self.GetAngleClass is not None:
                     del self.GetAngleClass                  
                  # si appresta ad attendere l'angolo di rotazione                      
                  self.GetAngleClass = QadGetAngleClass(self.plugIn)
                  prompt = QadMsg.translate("Command_INSERT", "Specify the symbol rotation <{0}>: ")
                  self.GetAngleClass.msg = prompt.format(str(qad_utils.toDegrees(self.rot)))
                  self.GetAngleClass.angle = self.rot
                  self.GetAngleClass.startPt = self.insPt               
                  self.step = 3
                  self.GetAngleClass.run(msgMapTool, msg)         
                  return False
               else:
                  self.addFeature(currLayer)               
                  return True   
            else:
               return True   
         return False
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA ROTAZIONE (da step = 1 o 2)
      elif self.step == 3:
         if self.GetAngleClass.run(msgMapTool, msg) == True:
            if self.GetAngleClass.angle is not None:
               self.rot = self.GetAngleClass.angle
               self.plugIn.setLastRot(self.rot)
               self.addFeature(currLayer)
               return True # fine comando
            else:
               return True
         return False class QadTEXTCommandClass(QadCommandClass):

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

   def getName(self):
      return QadMsg.translate("Command_list", "TEXT")

   def getEnglishName(self):
      return "TEXT"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runTEXTCommand)
   
   def getIcon(self):
      return QIcon(":/plugins/qad/icons/text.png")

   def getNote(self):
      # impostare le note esplicative del comando
      return QadMsg.translate("Command_TEXT", "Inserts a text.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      self.insPt = None
      self.hText = self.plugIn.lastHText
      self.rot = self.plugIn.lastRot
      self.GetDistClass = None
      self.GetAngleClass = None
      self.labelFields = None
      self.labelFieldNamesNdx = 0      
      self.labelFieldValues = []

   def __del__(self):
      QadCommandClass.__del__(self)
      if self.GetDistClass is not None:
         del self.GetDistClass
      if self.GetAngleClass is not None:
         del self.GetAngleClass


   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      # quando si éin fase di richiesta distanza (altezza testo)
      if self.step == 2:
         return self.GetDistClass.getPointMapTool()
      # quando si éin fase di richiesta rotazione
      elif self.step == 3:
         return self.GetAngleClass.getPointMapTool()
      else:
         return QadCommandClass.getPointMapTool(self, drawMode)


   def getCurrentContextualMenu(self):
      # quando si éin fase di richiesta distanza (altezza testo)
      if self.step == 2:
         return self.GetDistClass.getCurrentContextualMenu()
      # quando si éin fase di richiesta rotazione
      elif self.step == 3:
         return self.GetAngleClass.getCurrentContextualMenu()
      else:
         return self.contextualMenu


   def addFeature(self, layer):
      transformedPoint = self.mapToLayerCoordinates(layer, self.insPt)
      g = QgsGeometry.fromPoint(transformedPoint)
      f = QgsFeature()
      f.setGeometry(g)
      # Add attribute fields to feature.
      fields = layer.pendingFields()
      f.setFields(fields)
      
      # assegno i valori di default
      provider = layer.dataProvider()
      for field in fields.toList():
         i = fields.indexFromName(field.name())
         f[field.name()] = provider.defaultValue(i)
      
      # se l'altezza testo dipende da un solo campo 
      sizeFldNames = qad_label.get_labelSizeFieldNames(layer)
      if len(sizeFldNames) == 1 and len(sizeFldNames[0]) > 0:
         f.setAttribute(sizeFldNames[0], self.hText)
      
      # se la rotazione dipende da un solo campo
      rotFldNames = qad_label.get_labelRotationFieldNames(layer)
      if len(rotFldNames) == 1 and len(rotFldNames[0]) > 0:
         f.setAttribute(rotFldNames[0], qad_utils.toDegrees(self.rot))
         
      # setto i valori degli attributi che compongono l'etichetta
      i = 0
      tot = len(self.labelFields)
      while i < tot:
         f.setAttribute(self.labelFields[i].name(), self.labelFieldValues[i])
         i = i + 1
      
      return qad_layer.addFeatureToLayer(self.plugIn, layer, f)       

   def initLabelFields(self, layer):
      labelFieldNames = qad_label.get_labelFieldNames(layer)
      if len(labelFieldNames) > 0:
         self.labelFields = QgsFields()         
         for field in layer.dataProvider().fields():   
            if field.name() in labelFieldNames:
               self.labelFields.append(QgsField(field.name(), field.type()))
    
   #============================================================================
   # waitForFieldValue
   #============================================================================
   def waitForFieldValue(self):      
      self.step = 4      
      
      if self.labelFields is None:
         return False
      if self.labelFieldNamesNdx >= len(self.labelFields):
         return False
      field = self.labelFields[self.labelFieldNamesNdx]
      prompt = QadMsg.translate("Command_TEXT", "Enter the value of attribute \"{0}\": ").format(field.name())
      if field.type() == QVariant.Double: # si appresta ad attendere un double o valore nullo      
         self.waitForFloat(prompt, None, QadInputModeEnum.NONE)
      elif field.type() == QVariant.LongLong: # si appresta ad attendere un long a 64 bit o valore nullo       
         self.waitForLong(prompt, None, QadInputModeEnum.NONE)
      elif field.type() == QVariant.Int: # si appresta ad attendere un integer o valore nullo     
         self.waitForInt(prompt, None, QadInputModeEnum.NONE)
      elif field.type() == QVariant.Bool: # si appresta ad attendere un boolean o valore nullo
         self.waitForBool(prompt, None, QadInputModeEnum.NONE)
      else: # si appresta ad attendere una stringa o valore nullo
         self.waitForString(prompt, None, QadInputModeEnum.NONE)
                  
      return True
   
      
   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
      
      currLayer, errMsg = qad_layer.getCurrLayerEditable(self.plugIn.canvas, QGis.Point)
      if currLayer is None:
         self.showErr(errMsg)
         return True # fine comando

      if qad_layer.isTextLayer(currLayer) == False:
         errMsg = QadMsg.translate("QAD", "\nCurrent layer is not a textual layer.")
         errMsg = errMsg + QadMsg.translate("QAD", "\nA textual layer is a vector punctual layer having a label and the symbol transparency no more than 10%.\n")
         self.showErr(errMsg)         
         return True # fine comando

               
      #=========================================================================
      # RICHIESTA PUNTO DI INSERIMENTO
      if self.step == 0: # inizio del comando
         self.waitForPoint() # si appresta ad attendere un punto
         self.step = self.step + 1
         return False
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA PUNTO DI INSERIMENTO
      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
               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

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

         self.insPt = QgsPoint(pt)
         self.plugIn.setLastPoint(self.insPt)
         
         # se l'altezza testo dipende da un solo campo 
         sizeFldNames = qad_label.get_labelSizeFieldNames(currLayer)
         if len(sizeFldNames) == 1 and len(sizeFldNames[0]) > 0:
            # si appresta ad attendere la scala                      
            self.GetDistClass = QadGetDistClass(self.plugIn)
            prompt = QadMsg.translate("Command_TEXT", "Specify the text height <{0}>: ")
            self.GetDistClass.msg = prompt.format(str(self.hText))
            self.GetDistClass.dist = self.hText
            self.GetDistClass.inputMode = QadInputModeEnum.NOT_NEGATIVE | QadInputModeEnum.NOT_ZERO
            self.GetDistClass.startPt = self.insPt
            self.step = 2
            self.GetDistClass.run(msgMapTool, msg)
            return False
         else: 
            # se la rotazione dipende da un solo campo
            rotFldNames = qad_label.get_labelRotationFieldNames(currLayer)
            if len(rotFldNames) == 1 and len(rotFldNames[0]) > 0:
               if self.GetAngleClass is not None:
                  del self.GetAngleClass                  
               # si appresta ad attendere l'angolo di rotazione                      
               self.GetAngleClass = QadGetAngleClass(self.plugIn)
               prompt = QadMsg.translate("Command_TEXT", "Specify the text rotation <{0}>: ")
               self.GetAngleClass.msg = prompt.format(str(qad_utils.toDegrees(self.rot)))
               self.GetAngleClass.angle = self.rot
               self.GetAngleClass.startPt = self.insPt               
               self.step = 3
               self.GetAngleClass.run(msgMapTool, msg)               
               return False
            else:
               self.initLabelFields(currLayer)
               if self.waitForFieldValue() == False:
                  self.addFeature(currLayer)
                  return True

         return False
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA ALTEZZA TESTO (da step = 1)
      elif self.step == 2:
         if self.GetDistClass.run(msgMapTool, msg) == True:
            if self.GetDistClass.dist is not None:
               self.hText = self.GetDistClass.dist
               self.plugIn.setLastHText(self.hText)
               del self.GetDistClass
               self.GetDistClass = None
                
               # se la rotazione dipende da un solo campo
               rotFldNames = qad_label.get_labelRotationFieldNames(currLayer)
               if len(rotFldNames) == 1 and len(rotFldNames[0]) > 0:
                  if self.GetAngleClass is not None:
                     del self.GetAngleClass                  
                  # si appresta ad attendere l'angolo di rotazione                      
                  self.GetAngleClass = QadGetAngleClass(self.plugIn)
                  prompt = QadMsg.translate("Command_TEXT", "Specify the text rotation <{0}>: ")
                  self.GetAngleClass.msg = prompt.format(str(qad_utils.toDegrees(self.rot)))
                  self.GetAngleClass.angle = self.rot
                  self.GetAngleClass.startPt = self.insPt               
                  self.step = 3
                  self.GetAngleClass.run(msgMapTool, msg)         
                  return False
               else:
                  self.initLabelFields(currLayer)
                  if self.waitForFieldValue() == False:
                     self.addFeature(currLayer)               
                     return True
            else:
               return True   
         return False
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA ROTAZIONE (da step = 1 o 2)
      elif self.step == 3:
         if self.GetAngleClass.run(msgMapTool, msg) == True:
            if self.GetAngleClass.angle is not None:
               self.rot = self.GetAngleClass.angle
               self.plugIn.setLastRot(self.rot)
               self.initLabelFields(currLayer)
               if self.waitForFieldValue() == False:
                  self.addFeature(currLayer)
                  return True # fine comando               
            else:
               return True
         return False

      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL VALORE DI UN CAMPO
      elif self.step == 4: # dopo aver atteso un valore si riavvia il comando
         if msgMapTool == True: # il punto arriva da una selezione grafica
            self.waitForFieldValue()
            return False
         # il valore arriva come parametro della funzione
         self.labelFieldValues.append(msg)
         self.labelFieldNamesNdx = self.labelFieldNamesNdx + 1 
         if self.waitForFieldValue() == False:
            self.addFeature(currLayer)
            return True # fine comando
         
         return False class QadSTRETCHCommandClass(QadCommandClass):

   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadSTRETCHCommandClass(self.plugIn)
   
   def getName(self):
      return QadMsg.translate("Command_list", "STRETCH")

   def getEnglishName(self):
      return "STRETCH"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runSTRETCHCommand)

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/stretch.png")

   def getNote(self):
      # impostare le note esplicative del comando
      return QadMsg.translate("Command_STRETCH", "Stretches objects.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      self.AddOnSelection = True # se = False significa remove
      self.points = []
      self.MPOLYGONCommand = None
      self.SSGeomList = [] # lista di entità da stirare con geom di selezione
      self.basePt = QgsPoint()
   
   def __del__(self):
      QadCommandClass.__del__(self)
      if self.MPOLYGONCommand is not None:
         del self.MPOLYGONCommand      
      for SSGeom in self.SSGeomList:
         SSGeom[0].deselectOnLayer()


   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      if self.step == 2: # quando si é in fase di disegno linea
         return self.MPOLYGONCommand.getPointMapTool(drawMode)
      else:
         if (self.plugIn is not None):
            if self.PointMapTool is None:
               self.PointMapTool = Qad_stretch_maptool(self.plugIn)
            return self.PointMapTool
         else:
            return None


   def getCurrentContextualMenu(self):
      if self.step == 2: # quando si é in fase di disegno linea
         return self.MPOLYGONCommand.getCurrentContextualMenu()
      else:
         return self.contextualMenu


   def stretch(self, entity, containerGeom, 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.stretchQgsGeometry(stretchedGeom, containerGeom, \
                                                            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)
            # plugIn, layer, feature, refresh, check_validity
            if qad_layer.updateFeatureToLayer(self.plugIn, entity.layer, f, False, False) == False:
               return False

      elif entity.whatIs() == "DIMENTITY":
         # stiro la quota
         if entity.deleteToLayers(self.plugIn) == False:
            return False
         newDimEntity = QadDimEntity(entity) # la copio
         newDimEntity.stretch(containerGeom, offSetX, offSetY)
         if newDimEntity.addToLayers(self.plugIn) == False:
            return False             
            
      return True


   #============================================================================
   # stretchFeatures
   #============================================================================
   def stretchFeatures(self, newPt):
      # mi ricavo un unico QadEntitySet con le entità selezionate
      entitySet = QadEntitySet()
      for SSGeom in self.SSGeomList:
         entitySet.unite(SSGeom[0])
      self.plugIn.beginEditCommand("Feature stretched", entitySet.getLayerList())
      
      dimElaboratedList = [] # lista delle quotature già elaborate

      tolerance2ApproxCurve = QadVariables.get(QadMsg.translate("Environment variables", "TOLERANCE2APPROXCURVE"))
      offSetX = newPt.x() - self.basePt.x()
      offSetY = newPt.y() - self.basePt.y()
      
      entity = QadEntity()
      for SSGeom in self.SSGeomList:
         # copio entitySet
         entitySet = QadEntitySet(SSGeom[0])
         geomSel = SSGeom[1]

         for layerEntitySet in entitySet.layerEntitySetList:
            layer = layerEntitySet.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.stretch(entity, geomSel, 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
                     dimElaboratedList.append(dimEntity)
                     if self.stretch(dimEntity, geomSel, offSetX, offSetY, tolerance2ApproxCurve) == False:
                        self.plugIn.destroyEditCommand()
                        return

      self.plugIn.endEditCommand()


   #============================================================================
   # setEntitySetGeom
   #============================================================================
   def setEntitySetGeom(self, entitySet, selGeom):
      for SSGeom in self.SSGeomList:
         SSGeom[0].deselectOnLayer()
      del self.SSGeomList[:] # svuoto la lista  
      # aggiuge il gruppo di selezione con la geometria usata per la selezione
      self.SSGeomList.append([entitySet, selGeom])
      entitySet.selectOnLayer(False) # incremental = False

   #============================================================================
   # addEntitySetGeom
   #============================================================================
   def addEntitySetGeom(self, entitySet, selGeom):      
      # elimino dai gruppi precedenti gli oggetti presenti in entitySet
      self.removeEntitySet(entitySet)
      # aggiuge il gruppo di selezione con la geometria usata per la selezione
      self.SSGeomList.append([entitySet, selGeom])
      entitySet.selectOnLayer(True) # incremental = True
                                                      

   #============================================================================
   # removeEntitySet
   #============================================================================
   def removeEntitySet(self, entitySet):
      # elimino dai gruppi precedenti gli oggetti presenti in entitySet
      for SSGeom in self.SSGeomList:
         SSGeom[0].subtract(entitySet)
      for SSGeom in self.SSGeomList:
         SSGeom[0].selectOnLayer(False) # incremental = False


   #============================================================================
   # SSGeomListIsEmpty
   #============================================================================
   def SSGeomListIsEmpty(self):
      if len(self.SSGeomList) == 0:
         return True      
      for SSGeom in self.SSGeomList:
         if SSGeom[0].isEmpty() == False:
            return False
      return True

      
   #============================================================================
   # waitForObjectSel
   #============================================================================
   def waitForObjectSel(self):      
      self.step = 1     
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_stretch_maptool_ModeEnum.ASK_FOR_FIRST_PT_RECTANGLE)                                
      
      keyWords = QadMsg.translate("Command_STRETCH", "Polygon") + "/" + \
                 QadMsg.translate("Command_STRETCH", "Add") + "/" + \
                 QadMsg.translate("Command_STRETCH", "Remove")

      if self.AddOnSelection == True:
         prompt = QadMsg.translate("Command_STRETCH", "Select vertices")
      else:
         prompt = QadMsg.translate("Command_STRETCH", "Remove vertices")
      prompt = prompt + QadMsg.translate("Command_STRETCH", " to stretch crossed by a selection window or [{0}]: ").format(keyWords)                        

      englishKeyWords = "Polygon" + "/" + "Add" + "/" + "Remove"
      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 = 4   
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_stretch_maptool_ModeEnum.NONE_KNOWN_ASK_FOR_BASE_PT)                                
      
      keyWords = QadMsg.translate("Command_STRETCH", "Displacement")
      prompt = QadMsg.translate("Command_STRETCH", "Specify base point or [{0}] <{0}>: ").format(keyWords)
         
      englishKeyWords = "Displacement"
      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)      


   #============================================================================
   # 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
         # si appresta ad attendere la selezione degli oggetti da stirare
         self.waitForObjectSel()
         return False
      
      #=========================================================================
      # RISPOSTA ALLA SELEZIONE OGGETTI DA STIRARE
      elif self.step == 1:
         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
         else: # il punto arriva come parametro della funzione
            value = msg

         if type(value) == unicode:
            if value == QadMsg.translate("Command_STRETCH", "Polygon") or value == "Polygon":
               # Seleziona tutti gli oggetti che sono interni al poligono
               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   
               self.MPOLYGONCommand.run(msgMapTool, msg)
               self.step = 2
               return False               
            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
            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                        
         elif type(value) == QgsPoint: # se é stato selezionato un punto
            del self.points[:] # svuoto la lista
            self.points.append(value)
            # imposto il map tool
            self.getPointMapTool().setMode(Qad_stretch_maptool_ModeEnum.FIRST_PT_KNOWN_ASK_FOR_SECOND_PT_RECTANGLE)                                            
            self.getPointMapTool().setStartPoint(value)
            
            # si appresta ad attendere un punto
            self.waitForPoint(QadMsg.translate("Command_STRETCH", "Specify opposite corner: "))
            self.step = 3
            return False                  
         else:
            if self.SSGeomListIsEmpty():
               return True
            # si appresta ad attendere il punto base o lo spostamento
            self.waitForBasePt()
            return False                  
         
         # si appresta ad attendere la selezione degli oggetti da stirare
         self.waitForObjectSel()
                                          
         return False 

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA PUNTO PER MODALITA' POLIGONO (da step = 1)
      elif self.step == 2: # dopo aver atteso un punto si riavvia il comando
         if self.MPOLYGONCommand.run(msgMapTool, msg) == True:
            if len(self.MPOLYGONCommand.vertices) > 1:
               # cerco tutte le geometrie intersecanti il poligono
               # e considerando solo layer editabili       
               selSet = qad_utils.getSelSet("CP", self.getPointMapTool(), self.MPOLYGONCommand.vertices, \
                                                 None, True, True, True, \
                                                 True)
               # se la selezione é avvenuta con shift premuto o se si deve rimuovere il gruppo selSet dal gruppo
               if self.AddOnSelection == False:
                  self.removeEntitySet(selSet)
               else:
                  self.setEntitySetGeom(selSet, QgsGeometry.fromPolygon([self.MPOLYGONCommand.vertices]))
                              
            del self.MPOLYGONCommand
            self.MPOLYGONCommand = None

            # si appresta ad attendere la selezione degli oggetti da stirare
            self.waitForObjectSel()                                 
            self.getPointMapTool().refreshSnapType() # aggiorno lo snapType che può essere variato dal maptool di mpolygon                     
         return False

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA PUNTO PER MODALITA' FINESTRA (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_STRETCH", "Window not correct."))
                  # si appresta ad attendere un punto
                  self.waitForPoint(QadMsg.translate("Command_STRETCH", "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.points.append(value)   
            # cerco tutte le geometrie intersecanti il rettangolo
            # e considerando solo layer editabili
            selSet = qad_utils.getSelSet("C", self.getPointMapTool(), self.points, \
                                         None, True, True, True, \
                                         True)            
            # se si deve rimuovere il gruppo entitySet dal gruppo
            if self.AddOnSelection == False:
               self.removeEntitySet(selSet)
            else:
               if shiftKey: # se la selezione é avvenuta con shift premuto
                  self.addEntitySetGeom(selSet, QgsGeometry.fromRect(QgsRectangle(self.points[0], self.points[1])))
               else:
                  self.setEntitySetGeom(selSet, QgsGeometry.fromRect(QgsRectangle(self.points[0], self.points[1])))
            # si appresta ad attendere la selezione degli oggetti da stirare
            self.waitForObjectSel()                                 
         return False
              
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA PUNTO BASE (da step = 1)
      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
                  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

         # imposto il map tool
         self.getPointMapTool().SSGeomList = self.SSGeomList

         if value is None or type(value) == unicode:
            self.basePt.set(0, 0)
            self.getPointMapTool().basePt = self.basePt
            self.getPointMapTool().setMode(Qad_stretch_maptool_ModeEnum.BASE_PT_KNOWN_ASK_FOR_MOVE_PT)                                
            # si appresta ad attendere un punto
            msg = QadMsg.translate("Command_STRETCH", "Specify the displacement from the origin point 0,0 <{0}, {1}>: ")
            # msg, inputType, default, keyWords, nessun controllo
            self.waitFor(msg.format(str(self.plugIn.lastOffsetPt.x()), str(self.plugIn.lastOffsetPt.y())), \
                         QadInputTypeEnum.POINT2D, \
                         self.plugIn.lastOffsetPt, \
                         "", QadInputModeEnum.NONE)                                      
            self.step = 5      
         elif 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().setMode(Qad_stretch_maptool_ModeEnum.BASE_PT_KNOWN_ASK_FOR_MOVE_PT)                                
            
            # si appresta ad attendere un punto o enter o una parola chiave         
            # msg, inputType, default, keyWords, nessun controllo
            self.waitFor(QadMsg.translate("Command_STRETCH", "Specify second point or [Array] <use first point as displacement from origin point 0,0>: "), \
                         QadInputTypeEnum.POINT2D, \
                         None, \
                         "", QadInputModeEnum.NONE)      
            self.step = 6      
         
         return False 

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL PUNTO DI SPOSTAMENTO (da step = 2)
      elif self.step == 5: # 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.plugIn.setLastOffsetPt(value)
         self.stretchFeatures(value)
         return True # fine comando     
         
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA SECONDO PUNTO PER SPOSTAMENTO (da step = 2)
      elif self.step == 6: # 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 value is None:
            newPt = QgsPoint(self.basePt.x() * 2, self.basePt.y() * 2)
            self.stretchFeatures(newPt)
         elif type(value) == QgsPoint: # se é stato inserito lo spostamento con un punto
            self.stretchFeatures(value)
            
         return True # fine comando class QadBREAKCommandClass(QadCommandClass):

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

   def getName(self):
      return QadMsg.translate("Command_list", "BREAK")

   def getEnglishName(self):
      return "BREAK"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runBREAKCommand)

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/break.png")
   
   def getNote(self):
      # impostare le note esplicative del comando      
      return QadMsg.translate("Command_BREAK", "Breaks an object.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      self.entSelClass = None      
      self.firstPt = None
      self.secondPt = None

   def __del__(self):
      QadCommandClass.__del__(self)
      if self.entSelClass is not None:
         self.entSelClass.entity.deselectOnLayer()
         del self.entSelClass

   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      if self.step == 1: # quando si é in fase di selezione entità
         return self.entSelClass.getPointMapTool(drawMode)
      else:
         return QadCommandClass.getPointMapTool(self, drawMode)


   def getCurrentContextualMenu(self):
      if self.step == 1: # quando si é in fase di selezione entità
         return self.entSelClass.getCurrentContextualMenu()
      else:
         return self.contextualMenu


   def waitForEntsel(self, msgMapTool, msg):
      if self.entSelClass is not None:
         del self.entSelClass
      self.step = 1         
      self.entSelClass = QadEntSelClass(self.plugIn)
      self.entSelClass.msg = QadMsg.translate("Command_BREAK", "Select the object to break: ")
      # scarto la selezione di punti e poligoni
      self.entSelClass.checkPointLayer = False
      self.entSelClass.checkLineLayer = True
      self.entSelClass.checkPolygonLayer = False
      self.entSelClass.checkDimLayers = False
      self.entSelClass.onlyEditableLayers = True

      self.entSelClass.run(msgMapTool, msg)


   #============================================================================
   # breakFeatures
   #============================================================================
   def breakFeatures(self):
      f = self.entSelClass.entity.getFeature()
      if f is None:
         return
      
      layer = self.entSelClass.entity.layer
      LineTempLayer = None
      self.plugIn.beginEditCommand("Feature broken", layer)
      
      tolerance2ApproxCurve = QadVariables.get(QadMsg.translate("Environment variables", "TOLERANCE2APPROXCURVE"))                           

      # trasformo la geometria nel crs del canvas per lavorare con coordinate piane xy
      g = self.layerToMapCoordinates(layer, f.geometry())         
      result = qad_utils.breakQgsGeometry(g, self.firstPt, self.secondPt, \
                                          tolerance2ApproxCurve)                  
      if result is not None:
         line1 = result[0]
         line2 = result[1]
         atSubGeom = result[2]
         if layer.geometryType() == QGis.Line:
            if line1 is not None:
               updGeom = qad_utils.setSubGeom(g, line1, atSubGeom)
               if updGeom is None:
                  self.plugIn.destroyEditCommand()
                  return
               brokenFeature1 = QgsFeature(f)
               # trasformo la geometria nel crs del layer
               brokenFeature1.setGeometry(self.mapToLayerCoordinates(layer, updGeom))
               # plugIn, layer, feature, refresh, check_validity
               if qad_layer.updateFeatureToLayer(self.plugIn, layer, brokenFeature1, False, False) == False:
                  self.plugIn.destroyEditCommand()
                  return
            if line2 is not None:
               brokenFeature2 = QgsFeature(f)      
               # trasformo la geometria nel crs del layer
               brokenFeature2.setGeometry(self.mapToLayerCoordinates(layer, line2))
               # plugIn, layer, feature, coordTransform, refresh, check_validity
               if qad_layer.addFeatureToLayer(self.plugIn, layer, brokenFeature2, None, False, False) == False:
                  self.plugIn.destroyEditCommand()
                  return            
         else:
            # aggiungo le linee nei layer temporanei di QAD
            if LineTempLayer is None:
               LineTempLayer = qad_layer.createQADTempLayer(self.plugIn, QGis.Line)
               self.plugIn.addLayerToLastEditCommand("Feature broken", LineTempLayer)
            
            lineGeoms = []
            if line1 is not None:
               lineGeoms.append(line1)
            if line2 is not None:
               lineGeoms.append(line2)

            # trasformo la geometria in quella dei layer temporanei
            # plugIn, pointGeoms, lineGeoms, polygonGeoms, coord, refresh
            if qad_layer.addGeometriesToQADTempLayers(self.plugIn, None, lineGeoms, None, None, False) == False:
               self.plugIn.destroyEditCommand()
               return
            
            updGeom = qad_utils.delSubGeom(g, atSubGeom)

            if updGeom is None or updGeom.isGeosEmpty(): # da cancellare
               # plugIn, layer, feature id, refresh
               if qad_layer.deleteFeatureToLayer(self.plugIn, layer, f.id(), False) == False:
                  self.plugIn.destroyEditCommand()
                  return
            else:
               brokenFeature1 = QgsFeature(f)
               # trasformo la geometria nel crs del layer
               brokenFeature1.setGeometry(self.mapToLayerCoordinates(layer, updGeom))
               # plugIn, layer, feature, refresh, check_validity
               if qad_layer.updateFeatureToLayer(self.plugIn, layer, brokenFeature1, False, False) == False:
                  self.plugIn.destroyEditCommand()
                  return

      self.plugIn.endEditCommand()

       
   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
      
      if self.step == 0:     
         self.waitForEntsel(msgMapTool, msg)
         return False # continua
      
      #=========================================================================
      # RISPOSTA ALLA SELEZIONE DI UN'ENTITA' (da step = 0)
      elif self.step == 1:
         if self.entSelClass.run(msgMapTool, msg) == True:
            if self.entSelClass.entity.isInitialized():
               layer = self.entSelClass.entity.layer
               self.firstPt = self.entSelClass.point
               self.plugIn.setLastPoint(self.firstPt)
               
               keyWords = QadMsg.translate("Command_BREAK", "First point")
               prompt = QadMsg.translate("Command_BREAK", "Specify second break point or [{0}]: ").format(keyWords)
               
               self.step = 2
               self.getPointMapTool().refreshSnapType() # aggiorno lo snapType che può essere variato dal maptool di selezione entità
                                   
               englishKeyWords = "First point"
               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 False
            else:
               if self.entSelClass.canceledByUsr == True: # fine comando
                  return True
               self.showMsg(QadMsg.translate("QAD", "No geometries in this position."))
               self.waitForEntsel(msgMapTool, msg)
         return False # continua

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL SECONDO PUNTO DI INTERRUZIONE (da step = 1)
      elif self.step == 2: # dopo aver atteso un punto 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
                  pass # opzione di default "secondo punto"
               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 value is None or type(value) == unicode:
            # si appresta ad attendere un punto
            self.waitForPoint(QadMsg.translate("Command_BREAK", "Specify first break point: "))            
            self.step = 3
         elif type(value) == QgsPoint: # se é stato inserito il secondo punto
            self.secondPt = value
            self.plugIn.setLastPoint(self.secondPt)
            self.breakFeatures()            
            return True
         
         return False 

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL PRIMO PUNTO DI INTERRUZIONE (da step = 2)
      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
                  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.firstPt =  value
         self.plugIn.setLastPoint(self.firstPt)

         # si appresta ad attendere un punto
         self.waitForPoint(QadMsg.translate("Command_BREAK", "Specify second break point: "))            
         self.step = 4
         
         return False

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL SECONDO PUNTO DI INTERRUZIONE (da step = 3)
      elif self.step == 4: # 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
                  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.secondPt = value
         self.plugIn.setLastPoint(self.secondPt)
         self.breakFeatures()            
         
         return True class QadPEDITCommandClass(QadCommandClass):

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

   def getName(self):
      return QadMsg.translate("Command_list", "PEDIT")
   
   def getEnglishName(self):
      return "PEDIT"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runPEDITCommand)

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/pedit.png")
   
   def getNote(self):
      # impostare le note esplicative del comando      
      return QadMsg.translate("Command_PEDIT", "Modifies existing polylines or polygon.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      self.SSGetClass = QadSSGetClass(plugIn)
      self.SSGetClass.onlyEditableLayers = True
      self.SSGetClass.checkPointLayer = False # scarto i punto
      self.SSGetClass.checkLineLayer = True
      self.SSGetClass.checkDimLayers = False # scarto le quote
      
      self.entitySet = QadEntitySet()
      self.entity = QadEntity()
      self.atSubGeom = None
      self.linearObjectList = qad_utils.QadLinearObjectList()
      self.joinToleranceDist = plugIn.joinToleranceDist
      self.joinMode = plugIn.joinMode

      self.editVertexMode = None
      self.nOperationsToUndo = 0
         
      self.firstPt = QgsPoint()
      self.vertexAt = 0
      self.secondVertexAt = 0
      self.after = True
      self.snapPointsDisplayManager = QadSnapPointsDisplayManager(self.plugIn.canvas)
      self.snapPointsDisplayManager.setIconSize(QadVariables.get(QadMsg.translate("Environment variables", "AUTOSNAPSIZE")))
      self.snapPointsDisplayManager.setColor(QColor(QadVariables.get(QadMsg.translate("Environment variables", "AUTOSNAPCOLOR"))))

      self.GetDistClass = None
      self.simplifyTolerance = None
   
   def __del__(self):
      QadCommandClass.__del__(self)
      del self.SSGetClass
      self.entity.deselectOnLayer()
      self.entitySet.deselectOnLayer()
      del self.snapPointsDisplayManager
      if self.GetDistClass is not None: del self.GetDistClass


   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      if self.step == 2: # quando si é in fase di selezione entità
         return self.SSGetClass.getPointMapTool()           
      # quando si é in fase di richiesta distanza
      elif self.step == 12:
         return self.GetDistClass.getPointMapTool()
      else:
         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 getCurrentContextualMenu(self):
      if self.step == 2: # quando si é in fase di selezione entità
         return self.SSGetClass.getCurrentContextualMenu()
      # quando si é in fase di richiesta distanza
      elif self.step == 12:
         return self.GetDistClass.getCurrentContextualMenu()
      else:
         return self.contextualMenu


   #============================================================================
   # setEntityInfo
   #============================================================================
   def setEntityInfo(self, layer, featureId, point):
      """
      Setta self.entity, self.atSubGeom, self.linearObjectList
      """     
      self.entity.set(layer, featureId)
      geom = self.layerToMapCoordinates(layer, self.entity.getGeometry())
      # ritorna una tupla (<The squared cartesian distance>,
      #                    <minDistPoint>
      #                    <afterVertex>
      #                    <leftOf>)
      dummy = qad_utils.closestSegmentWithContext(point, 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())
         if self.linearObjectList.getCircle() is not None:
            self.entity.deselectOnLayer()
            return False
         else:
            self.entity.selectOnLayer(False) # non incrementale
            return True
      else:
         self.entity.deselectOnLayer()
         return False


   #============================================================================
   # getNextVertex
   #============================================================================
   def getNextVertex(self, vertexAt):
      """
      Ritorna la posizione del vertice successivo rispetto vertexAt
      """
      tot = self.linearObjectList.qty()
      if vertexAt == tot - 1: # se penultimo punto
         return 0 if self.linearObjectList.isClosed() else vertexAt + 1
      elif vertexAt < tot: # se non é ultimo punto
         return vertexAt + 1
      else:
         return vertexAt


   #============================================================================
   # getPrevVertex
   #============================================================================
   def getPrevVertex(self, vertexAt):
      """
      Ritorna la posizione del vertice precedente rispetto vertexAt
      """
      if vertexAt == 0: # se primo punto
         if self.linearObjectList.isClosed():
            return self.linearObjectList.qty() - 1
         else:
            return vertexAt
      else:
         return vertexAt - 1


   #============================================================================
   # displayVertexMarker
   #============================================================================
   def displayVertexMarker(self, vertexAt):
      if vertexAt == self.linearObjectList.qty():
         pt = self.linearObjectList.getLinearObjectAt(-1).getEndPt()
      else:
         pt = self.linearObjectList.getLinearObjectAt(vertexAt).getStartPt()
         
      # visualizzo il punto di snap
      snapPoint = dict()
      snapPoint[QadSnapTypeEnum.END] = [pt]
      self.snapPointsDisplayManager.show(snapPoint)
         

   #============================================================================
   # setClose
   #============================================================================
   def setClose(self, toClose):
      if self.entity.isInitialized(): # selezionato solo un oggetto
         layer = self.entity.layer
         self.plugIn.beginEditCommand("Feature edited", layer)
         
         tolerance2ApproxCurve = QadVariables.get(QadMsg.translate("Environment variables", "TOLERANCE2APPROXCURVE"))
         f = self.entity.getFeature()
         # trasformo la geometria nel crs del canvas per lavorare con coordinate piane xy
         geom = self.layerToMapCoordinates(layer, self.entity.getGeometry())
         geom = f.geometry()
         
         self.linearObjectList.setClose(toClose)
         pts = self.linearObjectList.asPolyline(tolerance2ApproxCurve)
         
         # trasformo la geometria nel crs del canvas per lavorare con coordinate piane xy
         geom = self.layerToMapCoordinates(layer, self.entity.getGeometry())
         
         if layer.geometryType() == QGis.Line:
            updGeom = qad_utils.setSubGeom(geom, QgsGeometry.fromPolyline(pts), self.atSubGeom)
            # trasformo la geometria nel crs del layer
            f.setGeometry(self.mapToLayerCoordinates(layer, updGeom))
               
            # plugIn, layer, feature, refresh, check_validity
            if qad_layer.updateFeatureToLayer(self.plugIn, layer, f, False, False) == False:
               self.plugIn.destroyEditCommand()
               return
         else: # layer di tipo poligono
            if toClose == False: # apri
               # aggiungo le linee nei layer temporanei di QAD
               LineTempLayer = qad_layer.createQADTempLayer(self.plugIn, QGis.Line)
               self.plugIn.addLayerToLastEditCommand("Feature edited", LineTempLayer)
                       
               lineGeoms = [QgsGeometry.fromPolyline(pts)]
               
               # trasformo la geometria in quella dei layer temporanei
               # plugIn, pointGeoms, lineGeoms, polygonGeoms, coord, refresh
               if qad_layer.addGeometriesToQADTempLayers(self.plugIn, None, lineGeoms, None, \
                                                         None, False) == False:
                  self.plugIn.destroyEditCommand()
                  return
               
               updGeom = qad_utils.delSubGeom(geom, atSubGeom)

               if updGeom is None or updGeom.isGeosEmpty(): # da cancellare
                  # plugIn, layer, feature id, refresh
                  if qad_layer.deleteFeatureToLayer(self.plugIn, layer, f.id(), False) == False:
                     self.plugIn.destroyEditCommand()
                     return
               else:
                  editedFeature = QgsFeature(f)
                  # trasformo la geometria nel crs del layer
                  editedFeature.setGeometry(self.mapToLayerCoordinates(layer, updGeom))
                  
                  # plugIn, layer, feature, refresh, check_validity
                  if qad_layer.updateFeatureToLayer(self.plugIn, layer, editedFeature, False, False) == False:
                     self.plugIn.destroyEditCommand()
                     return
      else:         
         self.plugIn.beginEditCommand("Feature edited", self.entitySet.getLayerList())
         for layerEntitySet in self.entitySet.layerEntitySetList:
            layer = layerEntitySet.layer
            tolerance2ApproxCurve = QadVariables.get(QadMsg.translate("Environment variables", "TOLERANCE2APPROXCURVE"))
            
            updObjects = []
            for featureId in layerEntitySet.featureIds:
               f = layerEntitySet.getFeature(featureId)
               # trasformo la geometria nel crs del canvas per lavorare con coordinate piane xy
               updGeom = qad_utils.closeQgsGeometry(self.mapToLayerCoordinates(layer, f.geometry()), toClose, tolerance2ApproxCurve)
               if updGeom is not None:
                  updFeature = QgsFeature(f)
                  # trasformo la geometria nel crs del layer
                  updFeature.setGeometry(self.mapToLayerCoordinates(layer, updGeom))
                  updObjects.append(updFeature)  
         
            # plugIn, layer, features, refresh, check_validity
            if qad_layer.updateFeaturesToLayer(self.plugIn, layer, updObjects, False, False) == False:
               self.plugIn.destroyEditCommand()
               return
   
      self.plugIn.endEditCommand()
      self.nOperationsToUndo = self.nOperationsToUndo + 1
      

   #============================================================================
   # reverse
   #============================================================================
   def reverse(self):
      if self.entity.isInitialized(): # selezionato solo un oggetto
         layer = self.entity.layer
         self.plugIn.beginEditCommand("Feature edited", layer)

         tolerance2ApproxCurve = QadVariables.get(QadMsg.translate("Environment variables", "TOLERANCE2APPROXCURVE"))
         f = self.entity.getFeature()
         # trasformo la geometria nel crs del canvas per lavorare con coordinate piane xy
         geom = self.layerToMapCoordinates(layer, self.entity.getGeometry())

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

         for layerEntitySet in self.entitySet.layerEntitySetList:
            tolerance2ApproxCurve = QadVariables.get(QadMsg.translate("Environment variables", "TOLERANCE2APPROXCURVE"))                       
            
            updObjects = []
            for featureId in layerEntitySet.featureIds:
               f = layerEntitySet.getFeature(featureId)
               # trasformo la geometria nel crs del canvas per lavorare con coordinate piane xy
               geom = self.layerToMapCoordinates(layerEntitySet.layer, f.geometry())               
               updGeom = qad_utils.reverseQgsGeometry(geom, tolerance2ApproxCurve)
               if updGeom is not None:
                  updFeature = QgsFeature(f)
                  # trasformo la geometria nel crs del layer
                  updFeature.setGeometry(self.mapToLayerCoordinates(layerEntitySet.layer, updGeom))
                  updObjects.append(updFeature)      
         
            # plugIn, layer, features, refresh, check_validity
            if qad_layer.updateFeaturesToLayer(self.plugIn, layerEntitySet.layer, updObjects, False, False) == False:
               self.plugIn.destroyEditCommand()
               return
   
      self.plugIn.endEditCommand()
      self.nOperationsToUndo = self.nOperationsToUndo + 1
      

   #============================================================================
   # join
   #============================================================================
   def join(self):
      tolerance2ApproxCurve = QadVariables.get(QadMsg.translate("Environment variables", "TOLERANCE2APPROXCURVE"))
      epsg = self.plugIn.canvas.currentLayer().crs().authid()
      # creo un layer temporaneo in memoria con campo numerico per 
      # contenere la posizione dell'entità originale nella lista newIdFeatureList
      vectorLayer = QgsVectorLayer("LineString?crs=%s&index=yes" % epsg, "QAD_SelfJoinLines", "memory")
      
      provider = vectorLayer.dataProvider()
      provider.addAttributes([QgsField('index', QVariant.Int, 'Int')])
      vectorLayer.updateFields()

      if vectorLayer.startEditing() == False:
         return

      # inserisco nel layer i vari oggetti lineari (WKBLineString)
      layerList = []
      newIdFeatureList = [] # lista ((newId - layer - feature) ...)
      i = 0
      
      if self.entity.isInitialized(): # selezionato solo un oggetto
         self.entitySet.removeEntity(self.entity) # elimino dal gruppo l'entità da unire
         
         # aggiungo l'entità a cui unirsi
         layer = self.entity.layer
         
         if layer.geometryType() != QGis.Line:
            return

         tolerance2ApproxCurve = QadVariables.get(QadMsg.translate("Environment variables", "TOLERANCE2APPROXCURVE"))
         
         f = self.entity.getFeature()
         if f.geometry().wkbType() != QGis.WKBLineString:
            return
         newFeature = QgsFeature()
         newFeature.initAttributes(1)
         newFeature.setAttribute(0, 0)
         
         geom = QgsGeometry.fromPolyline(self.linearObjectList.asPolyline(tolerance2ApproxCurve))
         newFeature.setGeometry(geom)
         i = i + 1
         
         if vectorLayer.addFeature(newFeature) == False:
            vectorLayer.destroyEditCommand()
            return
         newIdFeatureList.append([newFeature.id(), layer, f])
      
      
      for layerEntitySet in self.entitySet.layerEntitySetList:
         layer = layerEntitySet.layer
         
         if layer.geometryType() != QGis.Line:
            continue
                  
         for f in layerEntitySet.getFeatureCollection():
            if f.geometry().wkbType() != QGis.WKBLineString:
               continue
            newFeature = QgsFeature()
            newFeature.initAttributes(1)
            newFeature.setAttribute(0, i)

            # trasformo la geometria nel crs del canvas per lavorare con coordinate piane xy
            geom = self.layerToMapCoordinates(layerEntitySet.layer, f.geometry())
            newFeature.setGeometry(geom)
            i = i + 1
            
            if vectorLayer.addFeature(newFeature) == False:
               vectorLayer.destroyEditCommand()
               return
            newIdFeatureList.append([newFeature.id(), layer, f])
               
      vectorLayer.endEditCommand();
      vectorLayer.updateExtents()
        
      if provider.capabilities() & QgsVectorDataProvider.CreateSpatialIndex:
         provider.createSpatialIndex()

      deleteFeatures = []
      if self.entity.isInitialized(): # selezionato solo un oggetto
         featureIdToJoin = newIdFeatureList[0][0]
         #                         featureIdToJoin, vectorLayer, tolerance2ApproxCurve, toleranceDist, mode     
         deleteFeatures.extend(qad_utils.joinFeatureInVectorLayer(featureIdToJoin, vectorLayer, \
                                                                  tolerance2ApproxCurve, \
                                                                  self.joinToleranceDist, self.joinMode))
      else:         
         i = 0 
         tot = len(newIdFeatureList)
         while i < tot:
            featureIdToJoin = newIdFeatureList[i][0]
            #                         featureIdToJoin, vectorLayer, tolerance2ApproxCurve, toleranceDist, mode     
            deleteFeatures.extend(qad_utils.joinFeatureInVectorLayer(featureIdToJoin, vectorLayer, \
                                                                     tolerance2ApproxCurve, \
                                                                     self.joinToleranceDist, self.joinMode))
            i = i + 1
                       
      self.plugIn.beginEditCommand("Feature edited", self.entitySet.getLayerList())

      if self.entity.isInitialized(): # selezionato solo un oggetto
         newFeature = qad_utils.getFeatureById(vectorLayer, newIdFeatureList[0][0])
         if newFeature is None:
            self.plugIn.destroyEditCommand()
            return
         
         layer = newIdFeatureList[0][1]
         f = newIdFeatureList[0][2]

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

         updGeom = qad_utils.setSubGeom(geom, newFeature.geometry(), self.atSubGeom)

         # trasformo la geometria nel crs del layer
         f.setGeometry(self.mapToLayerCoordinates(self.entity.layer, updGeom))
         # plugIn, layer, feature, refresh, check_validity
         if qad_layer.updateFeatureToLayer(self.plugIn, layer, f, False, False) == False:
            self.plugIn.destroyEditCommand()
            return
      else:      
         # aggiorno la geometria delle features rimaste nel layer temporaneo
         # fetchAttributes, fetchGeometry, rectangle, useIntersect             
         for newFeature in vectorLayer.getFeatures(qad_utils.getFeatureRequest([], True, None, False)):
            layer = newIdFeatureList[newFeature['index']][1]
            f = newIdFeatureList[newFeature['index']][2]
            f.setGeometry(newFeature.geometry())
               
            # plugIn, layer, feature, refresh, check_validity
            if qad_layer.updateFeatureToLayer(self.plugIn, layer, f, False, False) == False:
               self.plugIn.destroyEditCommand()
               return
                          
      # cancello le features rimosse dal layer temporaneo
      for newFeature in deleteFeatures:
         layer = newIdFeatureList[newFeature['index']][1]
         f = newIdFeatureList[newFeature['index']][2]                          
         # plugIn, layer, feature id, refresh
         if qad_layer.deleteFeatureToLayer(self.plugIn, layer, f.id(), False) == False:
            self.plugIn.destroyEditCommand()
            return      
   
      self.plugIn.endEditCommand()
      self.nOperationsToUndo = self.nOperationsToUndo + 1


   #============================================================================
   # curve
   #============================================================================
   def curve(self, toCurve):
      if self.entity.isInitialized(): # selezionato solo un oggetto
         layer = self.entity.layer
         self.plugIn.beginEditCommand("Feature edited", layer)

         tolerance2ApproxCurve = QadVariables.get(QadMsg.translate("Environment variables", "TOLERANCE2APPROXCURVE"))
         f = self.entity.getFeature()
         # trasformo la geometria nel crs del canvas per lavorare con coordinate piane xy
         geom = self.layerToMapCoordinates(layer, f.geometry())

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

         for layerEntitySet in self.entitySet.layerEntitySetList:
            tolerance2ApproxCurve = QadVariables.get(QadMsg.translate("Environment variables", "TOLERANCE2APPROXCURVE"))  
            
            updObjects = []
            for featureId in layerEntitySet.featureIds:
               f = layerEntitySet.getFeature(featureId)
               # trasformo la geometria nel crs del canvas per lavorare con coordinate piane xy
               geom = self.layerToMapCoordinates(layerEntitySet.layer, f.geometry())
               
               updGeom = qad_utils.curveQgsGeometry(geom, toCurve, tolerance2ApproxCurve)
               if updGeom is not None:
                  updFeature = QgsFeature(f)
                  # trasformo la geometria nel crs del layer
                  updFeature.setGeometry(self.mapToLayerCoordinates(layerEntitySet.layer, updGeom))
                  updObjects.append(updFeature)      
         
            # plugIn, layer, features, refresh, check_validity
            if qad_layer.updateFeaturesToLayer(self.plugIn, layerEntitySet.layer, updObjects, False, False) == False:
               self.plugIn.destroyEditCommand()
               return
   
      self.plugIn.endEditCommand()
      self.nOperationsToUndo = self.nOperationsToUndo + 1


   #============================================================================
   # simplify
   #============================================================================
   def simplify(self):
      tolerance2ApproxCurve = QadVariables.get(QadMsg.translate("Environment variables", "TOLERANCE2APPROXCURVE"))
                             
      if self.entity.isInitialized(): # selezionato solo un oggetto
         layer = self.entity.layer
         self.plugIn.beginEditCommand("Feature edited", layer)
         
         f = self.entity.getFeature()
         # trasformo la geometria nel crs del canvas per lavorare con coordinate piane xy
         geom = self.layerToMapCoordinates(layer, f.geometry())

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

         for layerEntitySet in self.entitySet.layerEntitySetList:
            updObjects = []
            for featureId in layerEntitySet.featureIds:
               f = layerEntitySet.getFeature(featureId)
               # trasformo la geometria nel crs del canvas per lavorare con coordinate piane xy
               geom = self.layerToMapCoordinates(layerEntitySet.layer, f.geometry())               
               updGeom = geom.simplify(self.simplifyTolerance)
               if updGeom is not None:
                  updFeature = QgsFeature(f)
                  # trasformo la geometria nel crs del layer
                  updFeature.setGeometry(self.mapToLayerCoordinates(layerEntitySet.layer, updGeom))
                  updObjects.append(updFeature)      
         
            # plugIn, layer, features, refresh, check_validity
            if qad_layer.updateFeaturesToLayer(self.plugIn, layerEntitySet.layer, updObjects, False, False) == False:
               self.plugIn.destroyEditCommand()
               return
   
      self.plugIn.endEditCommand()
      self.nOperationsToUndo = self.nOperationsToUndo + 1


   #============================================================================
   # insertVertexAt
   #============================================================================
   def insertVertexAt(self, pt):         
      layer = self.entity.layer

      tolerance2ApproxCurve = QadVariables.get(QadMsg.translate("Environment variables", "TOLERANCE2APPROXCURVE"))
      f = self.entity.getFeature()
      # trasformo la geometria nel crs del canvas per lavorare con coordinate piane xy
      geom = self.layerToMapCoordinates(layer, f.geometry())

      if self.after: # dopo
         if self.vertexAt == self.linearObjectList.qty() and self.linearObjectList.isClosed():
            self.linearObjectList.insertPoint(0, pt)
         else:
            self.linearObjectList.insertPoint(self.vertexAt, pt)
      else: # prima
         if self.vertexAt == 0 and self.linearObjectList.isClosed():
            self.linearObjectList.insertPoint(self.linearObjectList.qty() - 1, pt)
         else:
            self.linearObjectList.insertPoint(self.vertexAt - 1, pt)
               
      updSubGeom = QgsGeometry.fromPolyline(self.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

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


   #============================================================================
   # moveVertexAt
   #============================================================================
   def moveVertexAt(self, pt):         
      layer = self.entity.layer

      tolerance2ApproxCurve = QadVariables.get(QadMsg.translate("Environment variables", "TOLERANCE2APPROXCURVE"))
      f = self.entity.getFeature()
      # trasformo la geometria nel crs del canvas per lavorare con coordinate piane xy
      geom = self.layerToMapCoordinates(layer, f.geometry())

      self.linearObjectList.movePoint(self.vertexAt, pt)
               
      updSubGeom = QgsGeometry.fromPolyline(self.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

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


   #============================================================================
   # straightenFromVertexAtToSecondVertexAt
   #============================================================================
   def straightenFromVertexAtToSecondVertexAt(self):
      if self.vertexAt == self.secondVertexAt:
         return
               
      layer = self.entity.layer
      tolerance2ApproxCurve = QadVariables.get(QadMsg.translate("Environment variables", "TOLERANCE2APPROXCURVE"))     
      f = self.entity.getFeature()
      # trasformo la geometria nel crs del canvas per lavorare con coordinate piane xy
      geom = self.layerToMapCoordinates(layer, f.geometry())

      if self.vertexAt < self.secondVertexAt:
         firstPt = self.linearObjectList.getPointAtVertex(self.vertexAt)
         secondPt = self.linearObjectList.getPointAtVertex(self.secondVertexAt)
         for i in xrange(self.vertexAt, self.secondVertexAt, 1):
            self.linearObjectList.remove(self.vertexAt)
         self.linearObjectList.insert(self.vertexAt, [firstPt, secondPt])
      elif self.vertexAt > self.secondVertexAt:
         if self.linearObjectList.isClosed():
            firstPt = self.linearObjectList.getPointAtVertex(self.vertexAt)
            secondPt = self.linearObjectList.getPointAtVertex(self.secondVertexAt)
            for i in xrange(self.vertexAt, self.linearObjectList.qty(), 1):
               self.linearObjectList.remove(self.vertexAt)
            for i in xrange(0, self.secondVertexAt, 1):
               self.linearObjectList.remove(0)
            
            self.linearObjectList.insert(self.vertexAt, [firstPt, secondPt])
         else:
            firstPt = self.linearObjectList.getPointAtVertex(self.secondVertexAt)
            secondPt = self.linearObjectList.getPointAtVertex(self.vertexAt)
            for i in xrange(self.secondVertexAt, self.vertexAt, 1):
               self.linearObjectList.remove(self.secondVertexAt)
            self.linearObjectList.insert(self.secondVertexAt, [firstPt, secondPt])
                       
      updSubGeom = QgsGeometry.fromPolyline(self.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

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


   #============================================================================
   # breakFromVertexAtToSecondVertexAt
   #============================================================================
   def breakFromVertexAtToSecondVertexAt(self):
      layer = self.entity.layer

      tolerance2ApproxCurve = QadVariables.get(QadMsg.translate("Environment variables", "TOLERANCE2APPROXCURVE"))
      f = self.entity.getFeature()
      # trasformo la geometria nel crs del canvas per lavorare con coordinate piane xy
      geom = self.layerToMapCoordinates(layer, f.geometry())

      firstPt = self.linearObjectList.getPointAtVertex(self.vertexAt)
      secondPt = self.linearObjectList.getPointAtVertex(self.secondVertexAt)

      result = qad_utils.breakQgsGeometry(QgsGeometry.fromPolyline(self.linearObjectList.asPolyline(tolerance2ApproxCurve)), \
                                          firstPt, secondPt, \
                                          tolerance2ApproxCurve)                  
      if result is None:
         return
      
      line1 = result[0]
      line2 = result[1]
      atSubGeom = result[2]
      
      updGeom = qad_utils.setSubGeom(geom, line1, 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, self.entity.layer, f, False, False) == False:
         self.plugIn.destroyEditCommand()
         return
      
      if line2 is not None:
         brokenFeature2 = QgsFeature(f)
         brokenFeature2.setGeometry(line2)
         # plugIn, layer, feature, coordTransform, refresh, check_validity
         if qad_layer.addFeatureToLayer(self.plugIn, layer, brokenFeature2, None, False, False) == False:
            self.plugIn.destroyEditCommand()
            return            

      self.linearObjectList.fromPolyline(line1.asPolyline())
      self.plugIn.endEditCommand()
      self.nOperationsToUndo = self.nOperationsToUndo + 1


   #============================================================================
   # waitForEntsel
   #============================================================================
   def waitForEntsel(self):      
      # imposto il map tool
      self.step = 1
      self.getPointMapTool().setMode(Qad_pedit_maptool_ModeEnum.ASK_FOR_ENTITY_SEL)
                        
      keyWords = QadMsg.translate("Command_PEDIT", "Last") + "/" + \
                 QadMsg.translate("Command_PEDIT", "Multiple")
      prompt = QadMsg.translate("Command_PEDIT", "Select polyline or [{0}]: ").format(QadMsg.translate("Command_PEDIT", "Multiple"))
               
      englishKeyWords = "Last" + "/" + "Multiple"
      keyWords += "_" + englishKeyWords
      # si appresta ad attendere un punto o enter o una parola chiave         
      # msg, inputType, default, keyWords, valore nullo non permesso
      self.waitFor(prompt, \
                   QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS, \
                   None, \
                   keyWords, QadInputModeEnum.NOT_NULL)      
      

   #============================================================================
   # WaitForMainMenu
   #============================================================================
   def WaitForMainMenu(self):
      # verifico se ci sono layer di tipo linea
      line = False
      if self.entity.isInitialized(): # selezionato solo un oggetto
         if self.entity.layer.geometryType() == QGis.Line:
            line = True
      else:            
         layerList = self.entitySet.getLayerList()
         for layer in layerList:
            if layer.geometryType() == QGis.Line:
               line = True
               break

      if line == True: # se ci sono dei layer linea
         if self.entity.isInitialized(): # selezionato solo un oggetto
            if self.linearObjectList.isClosed(): # se é chiusa
               keyWords = QadMsg.translate("Command_PEDIT", "Open") + "/"
               englishKeyWords = "Open"
            else:
               keyWords = QadMsg.translate("Command_PEDIT", "Close") + "/"
               englishKeyWords = "Close"
         else: # selezionati più oggetti
            keyWords = QadMsg.translate("Command_PEDIT", "Close") + "/" + \
                       QadMsg.translate("Command_PEDIT", "Open") + "/"
            englishKeyWords = "Close" + "/" + "Open"
                  
         keyWords = keyWords + QadMsg.translate("Command_PEDIT", "Join") + "/"
         englishKeyWords = englishKeyWords + "Join"
      else: # se non ci sono dei layer linea
         keyWords = ""
         msg = ""
         englishKeyWords = ""

      if self.entity.isInitialized(): # selezionato solo un oggetto
         keyWords = keyWords + QadMsg.translate("Command_PEDIT", "Edit vertex") + "/"
         englishKeyWords = englishKeyWords + "Edit vertex"
         
      keyWords = keyWords + QadMsg.translate("Command_PEDIT", "Fit") + "/" + \
                            QadMsg.translate("Command_PEDIT", "Decurve") + "/" + \
                            QadMsg.translate("Command_PEDIT", "Reverse") + "/" + \
                            QadMsg.translate("Command_PEDIT", "Simplify") + "/" + \
                            QadMsg.translate("Command_PEDIT", "Undo")      
      englishKeyWords = englishKeyWords + "Fit" + "/" + "Decurve" + "/" + "Reverse" + "/" + "Simplify" + "/" + "Undo"
      prompt = QadMsg.translate("Command_PEDIT", "Enter an option [{0}]: ").format(keyWords)
      
      self.step = 3
      self.getPointMapTool().setMode(Qad_pedit_maptool_ModeEnum.NONE)

      keyWords += "_" + englishKeyWords
      # si appresta ad attendere enter o una parola chiave         
      # msg, inputType, default, keyWords, nessun controllo
      self.waitFor(prompt, \
                   QadInputTypeEnum.KEYWORDS, \
                   None, \
                   keyWords, QadInputModeEnum.NONE)
      return False
      

   #============================================================================
   # WaitForJoin
   #============================================================================
   def WaitForJoin(self):
      CurrSettingsMsg = QadMsg.translate("QAD", "\nCurrent settings: ")
      CurrSettingsMsg = CurrSettingsMsg + QadMsg.translate("Command_PEDIT", "Join type = ")
      if self.joinMode == 1:
         CurrSettingsMsg = CurrSettingsMsg + QadMsg.translate("Command_PEDIT", "extends the segments")
      elif self.joinMode == 2:
         CurrSettingsMsg = CurrSettingsMsg + QadMsg.translate("Command_PEDIT", "adds segments")
      elif self.joinMode == 3:
         CurrSettingsMsg = CurrSettingsMsg + QadMsg.translate("Command_PEDIT", "extends and adds segments")
      
      self.showMsg(CurrSettingsMsg)
      self.waitForDistance()       
        

   #============================================================================
   # waitForDistance
   #============================================================================
   def waitForDistance(self):      
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_pedit_maptool_ModeEnum.ASK_FOR_FIRST_TOLERANCE_PT)

      keyWords = QadMsg.translate("Command_PEDIT", "Join type")                 
      prompt = QadMsg.translate("Command_PEDIT", "Specify gap tolerance or [{0}] <{1}>: ").format(keyWords, str(self.joinToleranceDist))

      englishKeyWords = "Join type"
      keyWords += "_" + englishKeyWords
      # si appresta ad attendere un punto o enter o una parola chiave o un numero reale     
      # msg, inputType, default, keyWords, nessun controllo
      self.waitFor(prompt, \
                   QadInputTypeEnum.POINT2D | QadInputTypeEnum.FLOAT | QadInputTypeEnum.KEYWORDS, \
                   self.joinToleranceDist, \
                   keyWords, \
                   QadInputModeEnum.NOT_NEGATIVE)      
      self.step = 4      
      
        
   #============================================================================
   # waitForJoinType
   #============================================================================
   def waitForJoinType(self):      
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_pedit_maptool_ModeEnum.NONE)

      keyWords = QadMsg.translate("Command_PEDIT", "Extend") + "/" + \
                 QadMsg.translate("Command_PEDIT", "Add") + "/" + \
                 QadMsg.translate("Command_PEDIT", "Both")
      englishKeyWords = "Extend" + "/" + "Add" + "/" + "Both"
      if self.joinMode == 1:
         default = QadMsg.translate("Command_PEDIT", "Extend")
      elif self.joinMode == 2:
         default = QadMsg.translate("Command_PEDIT", "Add")
      elif self.joinMode == 3:
         default = QadMsg.translate("Command_PEDIT", "Both")
      prompt = QadMsg.translate("Command_PEDIT", "Specify join type [{0}] <{1}>: ").format(keyWords, default)

      keyWords += "_" + englishKeyWords
      # si appresta ad attendere un punto o enter o una parola chiave o un numero reale     
      # msg, inputType, default, keyWords, nessun controllo
      self.waitFor(prompt, QadInputTypeEnum.KEYWORDS, default, \
                   keyWords)      
      self.step = 6


   #============================================================================
   # WaitForVertexEditingMenu
   #============================================================================
   def WaitForVertexEditingMenu(self):
      self.getPointMapTool().setLinearObjectList(self.linearObjectList, self.entity.layer)
      
      self.displayVertexMarker(self.vertexAt)
      
      keyWords = QadMsg.translate("Command_PEDIT", "Next") + "/" + \
                 QadMsg.translate("Command_PEDIT", "Previous")
      englishKeyWords = "Next" + "/" + "Previous"
      
      if self.entity.layer.geometryType() == QGis.Line:
         keyWords = keyWords + "/"  + QadMsg.translate("Command_PEDIT", "Break")
         englishKeyWords = englishKeyWords + "/" + "Break"

      keyWords = keyWords + "/" + QadMsg.translate("Command_PEDIT", "Insert") + "/" + \
                                  QadMsg.translate("Command_PEDIT", "INsert before") + "/" + \
                                  QadMsg.translate("Command_PEDIT", "Move") + "/" + \
                                  QadMsg.translate("Command_PEDIT", "Straighten") + "/" + \
                                  QadMsg.translate("Command_PEDIT", "eXit")
      englishKeyWords = englishKeyWords + "/" + "Insert" + "/" + "INsert before" + "/" + \
                                          "Move" + "/" + "Straighten" + "/" + "eXit"

      prompt = QadMsg.translate("Command_PEDIT", "Enter a vertex editing option [{0}] <{1}>: ").format(keyWords, self.default)
               
      self.step = 8
      self.getPointMapTool().setMode(Qad_pedit_maptool_ModeEnum.ASK_FOR_VERTEX)

      keyWords += "_" + englishKeyWords
      # si appresta ad attendere enter o una parola chiave         
      # msg, inputType, default, keyWords, nessun controllo
      self.waitFor(prompt, \
                   QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS, \
                   self.default, \
                   keyWords, QadInputModeEnum.NONE)
      return False


   #============================================================================
   # waitForNewVertex
   #============================================================================
   def waitForNewVertex(self):      
      # imposto il map tool
      self.getPointMapTool().setVertexAt(self.vertexAt, self.after)
      self.getPointMapTool().setMode(Qad_pedit_maptool_ModeEnum.ASK_FOR_NEW_VERTEX)

      # si appresta ad attendere un punto
      self.waitForPoint(QadMsg.translate("Command_PEDIT", "Specify the position of the new vertex: "))
      self.step = 9   


   #============================================================================
   # waitForMoveVertex
   #============================================================================
   def waitForMoveVertex(self):      
      # imposto il map tool
      self.getPointMapTool().setVertexAt(self.vertexAt)            
      self.getPointMapTool().setMode(Qad_pedit_maptool_ModeEnum.ASK_FOR_MOVE_VERTEX)

      # si appresta ad attendere un punto
      self.waitForPoint(QadMsg.translate("Command_PEDIT", "Specify the new vertex position: "))
      self.step = 10   


   #============================================================================
   # WaitForVertexEditingMenu
   #============================================================================
   def WaitForSecondVertex(self):
      self.displayVertexMarker(self.secondVertexAt)
      
      keyWords = QadMsg.translate("Command_PEDIT", "Next") + "/"  + \
                 QadMsg.translate("Command_PEDIT", "Previous") + "/"  + \
                 QadMsg.translate("Command_PEDIT", "Go") + "/"  + \
                 QadMsg.translate("Command_PEDIT", "eXit")
      englishKeyWords = "Next" + "/" + "Previous" + "/" + "Go" + "/" + "eXit"
      prompt = QadMsg.translate("Command_PEDIT", "Enter a selection option for the second vertex [{0}] <{1}>: ").format(keyWords, self.default1)
               
      self.getPointMapTool().setMode(Qad_pedit_maptool_ModeEnum.ASK_FOR_VERTEX)
      
      keyWords += "_" + englishKeyWords
      # si appresta ad attendere enter o una parola chiave         
      # msg, inputType, default, keyWords, nessun controllo
      self.waitFor(prompt, \
                   QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS, \
                   self.default1, \
                   keyWords, QadInputModeEnum.NONE)
      self.step = 11
      
      return False


   #============================================================================
   # WaitForSimplifyTolerance
   #============================================================================
   def WaitForSimplifyTolerance(self, msgMapTool, msg):
      if self.GetDistClass is not None:
         del self.GetDistClass
      self.GetDistClass = QadGetDistClass(self.plugIn)
      if self.simplifyTolerance is None:
         prompt = QadMsg.translate("Command_PEDIT", "Specify tolerance: ")
      else:
         prompt = QadMsg.translate("Command_PEDIT", "Specify tolerance <{0}>: ")
         self.GetDistClass.msg = prompt.format(str(self.simplifyTolerance))
         self.GetDistClass.dist = self.simplifyTolerance
      self.GetDistClass.inputMode = QadInputModeEnum.NOT_NEGATIVE
      self.step = 12
      self.GetDistClass.run(msgMapTool, msg)


   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
      
      if self.step == 0:     
         self.waitForEntsel()
         return False # continua
      
      #=========================================================================
      # RISPOSTA ALLA SELEZIONE OGGETTI
      elif self.step == 1:
         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
            else:
               value = self.getPointMapTool().point
         else: # il punto arriva come parametro della funzione
            value = msg

         if type(value) == unicode:
            if value == QadMsg.translate("Command_PEDIT", "Multiple") or value == "Multiple":
               self.SSGetClass.checkPolygonLayer = True               
               self.SSGetClass.run(msgMapTool, msg)
               self.step = 2
               return False               
         elif type(value) == QgsPoint: # se é stato selezionato un punto
            self.entity.clear()
            self.linearObjectList.removeAll()            

            if self.getPointMapTool().entity.isInitialized():
               if self.setEntityInfo(self.getPointMapTool().entity.layer, \
                                     self.getPointMapTool().entity.featureId, value) == True:
                  self.WaitForMainMenu()
                  return False
            else:               
               # cerco se ci sono entità nel punto indicato considerando
               # solo layer lineari o poligono editabili che non appartengano a quote
               layerList = []
               for layer in qad_utils.getVisibleVectorLayers(self.plugIn.canvas): # Tutti i layer vettoriali visibili
                  if (layer.geometryType() == QGis.Line or layer.geometryType() == QGis.Polygon) and \
                     layer.isEditable():
                     if len(QadDimStyles.getDimListByLayer(layer)) == 0:
                        layerList.append(layer)
               
               result = qad_utils.getEntSel(self.getPointMapTool().toCanvasCoordinates(value),
                                            self.getPointMapTool(), \
                                            QadVariables.get(QadMsg.translate("Environment variables", "PICKBOX")), \
                                            layerList)
               if result is not None:
                  # result[0] = feature, result[1] = layer, result[0] = point
                  if self.setEntityInfo(result[1], result[0].id(), result[2]) == True:
                     self.WaitForMainMenu()
                     return False                  
         else:
            return True # fine comando
         
         # si appresta ad attendere la selezione degli oggetti
         self.waitForEntsel()
         return False 

      #=========================================================================
      # RISPOSTA ALLA SELEZIONE DI UN GRUPPO OGGETTI
      elif self.step == 2:
         if self.SSGetClass.run(msgMapTool, msg) == True:         
            self.entitySet.set(self.SSGetClass.entitySet)
            
            if self.entitySet.count() == 0:
               self.waitForEntsel()
            else:
               self.WaitForMainMenu()
            self.getPointMapTool().refreshSnapType() # aggiorno lo snapType che può essere variato dal maptool di selezione entità                    
         return False
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL MENU PRINCIPALE (da step = 1 e 2)
      elif self.step == 3: # dopo aver atteso una opzione 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

            self.WaitForMainMenu()
            return False 
         else: # il punto arriva come parametro della funzione
            value = msg

         if value == QadMsg.translate("Command_PEDIT", "Close") or value == "Close":
            self.setClose(True) 
         elif value == QadMsg.translate("Command_PEDIT", "Open") or value == "Open":
            self.setClose(False) 
         elif value == QadMsg.translate("Command_PEDIT", "Edit vertex") or value == "Edit vertex":
            self.vertexAt = 0
            self.default = QadMsg.translate("Command_PEDIT", "Next")
            self.WaitForVertexEditingMenu()
            return False
         elif value == QadMsg.translate("Command_PEDIT", "Join") or value == "Join":
            if self.entity.isInitialized(): # selezionato solo un oggetto
               self.SSGetClass.checkPolygonLayer = False # scarto i poligoni
               self.SSGetClass.run(msgMapTool, msg)
               self.step = 7
               return False               
            else:
               self.WaitForJoin()
               return False
         elif value == QadMsg.translate("Command_PEDIT", "Fit") or value == "Fit":
            self.curve(True)
         elif value == QadMsg.translate("Command_PEDIT", "Decurve") or value == "Decurve":
            self.curve(False)
         elif value == QadMsg.translate("Command_PEDIT", "Reverse") or value == "Reverse":
            self.reverse()
         elif value == QadMsg.translate("Command_PEDIT", "Simplify") or value == "Simplify":
            self.WaitForSimplifyTolerance(msgMapTool, msg)
            return False
         elif value == QadMsg.translate("Command_PEDIT", "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."))                  
            
            if self.entity.isInitialized(): # selezionato solo un oggetto
               if self.atSubGeom is not None:
                  # ricarico la geometria ripristinata dall'annulla
                  geom = self.entity.getGeometry()
                  # ritorna la sotto-geometria al vertice <atVertex> e la sua posizione nella geometria (0-based)
                  subGeom = qad_utils.getSubGeomAt(geom, self.atSubGeom)
                  # trasformo la geometria nel crs del canvas per lavorare con coordinate piane xy
                  subGeom = self.layerToMapCoordinates(self.entity.layer, subGeom)
                  self.linearObjectList.fromPolyline(subGeom.asPolyline())
         else:
            return True # fine comando
            
         self.entity.deselectOnLayer()
         self.entitySet.deselectOnLayer()
         self.WaitForMainMenu()
         return False      
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DELLA DISTANZA DI APPROSSIMAZIONE (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
                  value = self.joinToleranceDist
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False
            else:
               value = self.getPointMapTool().point
         else: # il punto arriva come parametro della funzione
            value = msg
         
         if type(value) == unicode:
            if value == QadMsg.translate("Command_PEDIT", "Join type") or value == "Join type":
               # si appresta ad attendere il tipo di unione
               self.waitForJoinType()
         elif type(value) == QgsPoint: # se é stato inserito il primo punto per il calcolo della distanza
            # imposto il map tool
            self.firstPt.set(value.x(), value.y())
            self.getPointMapTool().firstPt = self.firstPt
            self.getPointMapTool().setMode(Qad_pedit_maptool_ModeEnum.FIRST_TOLERANCE_PT_KNOWN_ASK_FOR_SECOND_PT)

            # si appresta ad attendere un punto
            self.waitForPoint(QadMsg.translate("Command_PEDIT", "Specify second point: "))
            self.step = 5
         elif type(value) == float:
            self.joinToleranceDist = value
            self.plugIn.setJoinToleranceDist(self.joinToleranceDist)
            self.join()
            self.entity.deselectOnLayer()
            self.entitySet.deselectOnLayer()
            self.WaitForMainMenu()
         
         return False 
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA SECONDO PUNTO PER DISTANZA DI APPROSSIMAZIONE (da step = 4)
      elif self.step == 5: # 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 value == self.firstPt:
            self.showMsg(QadMsg.translate("QAD", "\nThe value must be positive and not zero."))
            # si appresta ad attendere un punto
            self.waitForPoint(QadMsg.translate("Command_PEDIT", "Specify second point: "))
            return False
         
         self.joinToleranceDist = qad_utils.getDistance(self.firstPt, value)
         self.plugIn.setJoinToleranceDist(self.joinToleranceDist)
         self.join()
         self.entity.deselectOnLayer()
         self.entitySet.deselectOnLayer()
         self.WaitForMainMenu()

         return False
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DELLA MODALITA' DI UNIONE (da step = 4)
      elif self.step == 6: # 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) == unicode:
            if value == QadMsg.translate("Command_PEDIT", "Extend") or value == "Extend":
               self.joinMode = 1
               self.plugIn.setJoinMode(self.joinMode)
            elif value == QadMsg.translate("Command_PEDIT", "Add") or value == "Add":
               self.joinMode = 2
               self.plugIn.setJoinMode(self.joinMode)
            elif value == QadMsg.translate("Command_PEDIT", "Both") or value == "Both":
               self.joinMode = 3
               self.plugIn.setJoinMode(self.joinMode)
            
         self.WaitForJoin()
         return False
      
      #=========================================================================
      # RISPOSTA ALLA SELEZIONE DI UN GRUPPO OGGETTI DA UNIRE (da step = 3)
      elif self.step == 7:
         if self.SSGetClass.run(msgMapTool, msg) == True:         
            self.entitySet.set(self.SSGetClass.entitySet)
            
            if self.entitySet.count() > 0:
               self.joinToleranceDist = 0.0
               self.join()

            self.entity.deselectOnLayer()
            self.entitySet.deselectOnLayer()
            self.WaitForMainMenu()
         return False
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DI OPZIONI EDITAZIONE VERTICI (da step = 3)
      elif self.step == 8: # dopo aver atteso un punto o una opzione 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
                  value = self.default
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False
            else:
               value = self.getPointMapTool().point
         else: # il punto o l'opzione arriva come parametro della funzione
            value = msg
         
         if type(value) == unicode:
            if value == QadMsg.translate("Command_PEDIT", "Next") or value == "Next":
               self.default = value
               self.vertexAt = self.getNextVertex(self.vertexAt)                                 
               self.WaitForVertexEditingMenu()
            elif value == QadMsg.translate("Command_PEDIT", "Previous") or value == "Previous":
               self.default = value
               self.vertexAt = self.getPrevVertex(self.vertexAt)
               self.WaitForVertexEditingMenu()
            elif value == QadMsg.translate("Command_PEDIT", "Break") or value == "Break":
               self.editVertexMode = QadMsg.translate("Command_PEDIT", "Break")
               self.secondVertexAt = self.vertexAt
               self.default1 = QadMsg.translate("Command_PEDIT", "Next")
               self.WaitForSecondVertex()
               return False
            elif value == QadMsg.translate("Command_PEDIT", "Insert") or value == "Insert":
               self.after = True
               self.waitForNewVertex()      
            elif value == QadMsg.translate("Command_PEDIT", "INsert before") or value == "INsert before":
               self.after = False
               self.waitForNewVertex()
            elif value == QadMsg.translate("Command_PEDIT", "Move") or value == "Move":
               self.waitForMoveVertex()
            elif value == QadMsg.translate("Command_PEDIT", "Straighten") or value == "Straighten":
               self.editVertexMode = QadMsg.translate("Command_PEDIT", "Straighten")
               self.secondVertexAt = self.vertexAt
               self.default1 = QadMsg.translate("Command_PEDIT", "Next")
               self.WaitForSecondVertex()
               return False
            elif value == QadMsg.translate("Command_PEDIT", "eXit") or value == "eXit":
               self.WaitForMainMenu()
         elif type(value) == QgsPoint: # se é stato inserito un punto
            # cerco il vertice più vicino al punto
            self.vertexAt = self.linearObjectList.closestVertexWithContext(value)
            self.WaitForVertexEditingMenu()
                                 
         return False 


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL NUOVO VERTICE DA INSERIRE (da step = 8)
      elif self.step == 9: # 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.insertVertexAt(value)
         self.vertexAt = self.vertexAt + (1 if self.after else -1)
         self.WaitForVertexEditingMenu()

         return False


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DELLA POSIZIONE DEL VERTICE DA SPOSTARE (da step = 8)
      elif self.step == 10: # 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.moveVertexAt(value)
         self.WaitForVertexEditingMenu()

         return False

      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL SECONDO VERTICE (da step = 8)
      elif self.step == 11: # dopo aver atteso un punto o una opzione 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
                  value = self.default
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False
            else:
               value = self.getPointMapTool().point
         else: # il punto o l'opzione arriva come parametro della funzione
            value = msg
         
         if type(value) == unicode:
            if value == QadMsg.translate("Command_PEDIT", "Next") or value == "Next":
               self.default1 = value
               self.secondVertexAt = self.getNextVertex(self.secondVertexAt)                                 
               self.WaitForSecondVertex()
            elif value == QadMsg.translate("Command_PEDIT", "Previous") or value == "Previous":
               self.default1 = value
               self.secondVertexAt = self.getPrevVertex(self.secondVertexAt)
               self.WaitForSecondVertex()
            elif value == QadMsg.translate("Command_PEDIT", "Go") or value == "Go":
               pt = self.linearObjectList.getPointAtVertex(self.vertexAt)
               
               if self.editVertexMode == QadMsg.translate("Command_PEDIT", "Break"):
                  self.breakFromVertexAtToSecondVertexAt()
               elif self.editVertexMode == QadMsg.translate("Command_PEDIT", "Straighten"):
                  self.straightenFromVertexAtToSecondVertexAt()
                  
               self.vertexAt = self.linearObjectList.getVertexPosAtPt(pt)
               self.WaitForVertexEditingMenu()
            elif value == QadMsg.translate("Command_PEDIT", "eXit") or value == "eXit":
               self.WaitForVertexEditingMenu()
         elif type(value) == QgsPoint: # se é stato inserito il primo punto
            # cerco il vertice più vicino al punto            
            self.secondVertexAt = self.linearObjectList.closestVertexWithContext(value)
            self.WaitForSecondVertex()
                                 
         return False 
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DELLA TOLLERANZE PER SEMPLIFICAZIONE (da step = 3)
      elif self.step == 12:
         if self.GetDistClass.run(msgMapTool, msg) == True:
            if self.GetDistClass.dist is not None:
               self.simplifyTolerance = self.GetDistClass.dist
               self.simplify()
               self.entity.deselectOnLayer()
               self.entitySet.deselectOnLayer()
               self.WaitForMainMenu()
         return False # fine comando class QadFILLETCommandClass(QadCommandClass):

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

   def getName(self):
      return QadMsg.translate("Command_list", "FILLET")

   def getEnglishName(self):
      return "FILLET"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runFILLETCommand)

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/fillet.png")
   
   def getNote(self):
      # impostare le note esplicative del comando      
      return QadMsg.translate("Command_FILLET", "Rounds and fillets the edges of objects.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)      
      self.GetDistClass = None

      self.entity1 = QadEntity()
      self.atSubGeom1 = None
      self.linearObjectList1 = qad_utils.QadLinearObjectList()
      self.partAt1 = 0
      self.pointAt1 = None
      
      self.entity2 = QadEntity()
      self.atSubGeom2 = None
      self.linearObjectList2 = qad_utils.QadLinearObjectList()
      self.partAt2 = 0
      self.pointAt2 = None

      self.filletMode = plugIn.filletMode # modalità di raccordo; 1=Taglia-estendi, 2=Non taglia-estendi
      self.radius = QadVariables.get(QadMsg.translate("Environment variables", "FILLETRAD"))
      self.multi = False
      self.nOperationsToUndo = 0
            
   
   def __del__(self):
      QadCommandClass.__del__(self)
      if self.GetDistClass is not None:
         del self.GetDistClass
      self.entity1.deselectOnLayer()
      self.entity2.deselectOnLayer()


   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      # quando si é in fase di richiesta distanza
      if self.step == 3 or self.step == 5 or self.step == 7:
         return self.GetDistClass.getPointMapTool()
      elif (self.plugIn is not None):
         if self.PointMapTool is None:
            self.PointMapTool = Qad_fillet_maptool(self.plugIn)
         return self.PointMapTool
      else:
         return None


   def getCurrentContextualMenu(self):
      # quando si é in fase di richiesta distanza
      if self.step == 3 or self.step == 5 or self.step == 7:
         return self.GetDistClass.getCurrentContextualMenu()
      else:
         return self.contextualMenu


   #============================================================================
   # setEntityInfo
   #============================================================================
   def setEntityInfo(self, firstObj, layer, featureId, point):
      """
      Setta self.entity, self.atSubGeom, self.linearObjectList, self.partAt, self.pointAt
      di primo o del secondo oggetto da raccordare (vedi <firstObj>)
      """
      if firstObj:
         e = self.entity1
         l = self.linearObjectList1
      else:
         e = self.entity2
         l = self.linearObjectList2
         
      e.set(layer, featureId)
      # trasformo la geometria nel crs del canvas per lavorare con coordinate piane xy
      geom = self.layerToMapCoordinates(layer, e.getGeometry())
      # ritorna una tupla (<The squared cartesian distance>,
      #                    <minDistPoint>
      #                    <afterVertex>
      #                    <leftOf>)
      dummy = qad_utils.closestSegmentWithContext(point, geom)
      if dummy[2] is not None:
         # ritorna la sotto-geometria al vertice <atVertex> e la sua posizione nella geometria (0-based)
         if firstObj:
            subGeom, self.atSubGeom1 = qad_utils.getSubGeomAtVertex(geom, dummy[2])
         else:
            subGeom, self.atSubGeom2 = qad_utils.getSubGeomAtVertex(geom, dummy[2])
             
         l.fromPolyline(subGeom.asPolyline())
         e.selectOnLayer(False) # non incrementale        
         
         # la funzione ritorna una lista con (<minima distanza al quadrato>,
         #                                    <punto più vicino>
         #                                    <indice della parte più vicina>       
         #                                    <"a sinistra di">)
         dummy = l.closestPartWithContext(point)
         
         if firstObj:           
            self.partAt1 = dummy[2]
            self.pointAt1 = dummy[1]
         else:
            self.partAt2 = dummy[2]
            self.pointAt2 = dummy[1]

         return True
      else:
         e.deselectOnLayer()
         return False


   #============================================================================
   # filletPolyline
   #============================================================================
   def filletPolyline(self):         
      layer = self.entity1.layer

      tolerance2ApproxCurve = QadVariables.get(QadMsg.translate("Environment variables", "TOLERANCE2APPROXCURVE"))
      f = self.entity1.getFeature()
      # trasformo la geometria nel crs del canvas per lavorare con coordinate piane xy
      geom = self.layerToMapCoordinates(layer, f.getGeometry())

      self.linearObjectList1.fillet(self.radius)
               
      updSubGeom = QgsGeometry.fromPolyline(self.linearObjectList1.asPolyline(tolerance2ApproxCurve))
      updGeom = qad_utils.setSubGeom(geom, updSubGeom, self.atSubGeom1)
      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)
      
      # 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()
      self.nOperationsToUndo = self.nOperationsToUndo + 1
      
      return True
   

   #============================================================================
   # fillet
   #============================================================================
   def fillet(self):
      tolerance2ApproxCurve = QadVariables.get(QadMsg.translate("Environment variables", "TOLERANCE2APPROXCURVE")) 
      
      # stessa entità e stessa parte
      if self.entity1.layer.id() == self.entity2.layer.id() and \
         self.entity1.featureId == self.entity2.featureId and \
         self.partAt1 == self.partAt2:
         return False
   
      # uso il crs del canvas per lavorare con coordinate piane xy
      epsg = self.plugIn.canvas.mapSettings().destinationCrs().authid()
      res = qad_utils.getFilletLinearObjectList(self.linearObjectList1, self.partAt1, self.pointAt1, \
                                                self.linearObjectList2, self.partAt2, self.pointAt2,\
                                                self.filletMode, self.radius, epsg)
      if res is None: # raccordo non possibile
         msg = QadMsg.translate("Command_FILLET", "\nFillet with radius <{0}> impossible.")
         #showMsg
         self.showMsg(msg.format(str(self.radius)))
         return False
      
      filletLinearObjectList = res[0]
      whatToDoPoly1 = res[1]
      whatToDoPoly2 = res[2]

      self.plugIn.beginEditCommand("Feature edited", [self.entity1.layer, self.entity2.layer])

      if whatToDoPoly1 == 1: # 1=modificare       
         f = self.entity1.getFeature()
         # trasformo la geometria nel crs del canvas per lavorare con coordinate piane xy
         geom = self.layerToMapCoordinates(self.entity1.layer, f.geometry())
         updSubGeom = QgsGeometry.fromPolyline(filletLinearObjectList.asPolyline(tolerance2ApproxCurve))
         updGeom = qad_utils.setSubGeom(geom, updSubGeom, self.atSubGeom1)
         if updGeom is None:
            self.plugIn.destroyEditCommand()
            return False
         # trasformo la geometria nel crs del layer
         f.setGeometry(self.mapToLayerCoordinates(self.entity1.layer, updGeom))
         
         # plugIn, layer, feature, refresh, check_validity
         if qad_layer.updateFeatureToLayer(self.plugIn, self.entity1.layer, f, False, False) == False:
            self.plugIn.destroyEditCommand()
            return False
      elif whatToDoPoly1 == 2: # 2=cancellare
         # se non si tratta della stessa entità
         if self.entity1 != self.entity2:
            # plugIn, layer, featureId, refresh
            if qad_layer.deleteFeatureToLayer(self.plugIn, self.entity1.layer, \
                                              self.entity1.featureId, False) == False:
               self.plugIn.destroyEditCommand()
               return False

      if whatToDoPoly2 == 1: # 1=modificare
         tolerance2ApproxCurve = QadVariables.get(QadMsg.translate("Environment variables", "TOLERANCE2APPROXCURVE"))

         f = self.entity2.getFeature()
         # trasformo la geometria nel crs del canvas per lavorare con coordinate piane xy
         geom = self.layerToMapCoordinates(self.entity2.layer, f.geometry())
         updSubGeom = QgsGeometry.fromPolyline(filletLinearObjectList.asPolyline(tolerance2ApproxCurve))
         updGeom = qad_utils.setSubGeom(geom, updSubGeom, self.atSubGeom2)
         if updGeom is None:
            self.plugIn.destroyEditCommand()
            return False
         # trasformo la geometria nel crs del layer
         f.setGeometry(self.mapToLayerCoordinates(self.entity2.layer, updGeom))
         
         # plugIn, layer, feature, refresh, check_validity
         if qad_layer.updateFeatureToLayer(self.plugIn, self.entity2.layer, f, False, False) == False:
            self.plugIn.destroyEditCommand()
            return False
      elif whatToDoPoly2 == 2: # 2=cancellare 
         # se non si tratta della stessa entità
         if self.entity1 != self.entity2:
            # plugIn, layer, featureId, refresh
            if qad_layer.deleteFeatureToLayer(self.plugIn, self.entity2.layer, \
                                              self.entity2.featureId, False) == False:
               self.plugIn.destroyEditCommand()
               return False

      if whatToDoPoly1 == 0 and whatToDoPoly2 == 0: # 0=niente      
         geom = QgsGeometry.fromPolyline(filletLinearObjectList.asPolyline(tolerance2ApproxCurve))
         # trasformo la geometria nel crs del layer
         geom = self.mapToLayerCoordinates(self.entity1.layer, geom)

         # plugIn, layer, geom, coordTransform, refresh, check_validity
         if qad_layer.addGeomToLayer(self.plugIn, self.entity1.layer, geom, None, False, False) == False:
            self.plugIn.destroyEditCommand()
            return False

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

      return True
      

   #============================================================================
   # waitForFirstEntSel
   #============================================================================
   def waitForFirstEntSel(self):      
      self.step = 1
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_fillet_maptool_ModeEnum.ASK_FOR_FIRST_LINESTRING)

      # l'opzione Radius viene tradotta in italiano in "RAggio" nel contesto "waitForFirstEntSel"
      keyWords = QadMsg.translate("Command_FILLET", "Undo") + "/" + \
                 QadMsg.translate("Command_FILLET", "Polyline") + "/" + \
                 QadMsg.translate("Command_FILLET", "Radius", "waitForFirstEntSel") + "/" + \
                 QadMsg.translate("Command_FILLET", "Trim") + "/" + \
                 QadMsg.translate("Command_FILLET", "Multiple")
      prompt = QadMsg.translate("Command_FILLET", "Select first object or [{0}]: ").format(keyWords)
               
      englishKeyWords = "Undo" + "/" + "Polyline" + "/" + "Radius" + "/" + "Trim" + "/" + "Multiple"
      keyWords += "_" + englishKeyWords
      # si appresta ad attendere un punto o enter o una parola chiave         
      # msg, inputType, default, keyWords, valore nullo non permesso
      self.waitFor(prompt, \
                   QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS, \
                   None, \
                   keyWords, QadInputModeEnum.NOT_NULL)      
      

   #============================================================================
   # WaitForPolyline
   #============================================================================
   def WaitForPolyline(self):
      self.step = 2
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_fillet_maptool_ModeEnum.ASK_FOR_POLYLINE)
      self.getPointMapTool().radius = self.radius      

      # l'opzione Radius viene tradotta in italiano in "Raggio" nel contesto "WaitForPolyline"
      keyWords = QadMsg.translate("Command_FILLET", "Radius", "WaitForPolyline")
      prompt = QadMsg.translate("Command_FILLET", "Select polyline or [{0}]: ").format(keyWords)

      englishKeyWords = "Radius"
      keyWords += "_" + englishKeyWords
      # si appresta ad attendere un punto o enter o una parola chiave         
      # msg, inputType, default, keyWords, valore nullo non permesso
      self.waitFor(prompt, \
                   QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS, \
                   None, \
                   keyWords, QadInputModeEnum.NOT_NULL)      
            
        
   #============================================================================
   # waitForFilletMode
   #============================================================================
   def waitForFilletMode(self):      
      self.step = 4
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_fillet_maptool_ModeEnum.NONE)

      keyWords = QadMsg.translate("Command_FILLET", "Trim-extend") + "/" + \
                 QadMsg.translate("Command_FILLET", "No trim-extend")

      if self.filletMode == 1:
         default = QadMsg.translate("Command_FILLET", "Trim-extend")
      elif self.filletMode == 2:
         default = QadMsg.translate("Command_FILLET", "No trim-extend") 
                         
      prompt = QadMsg.translate("Command_FILLET", "Specify trim mode [{0}] <{1}>: ").format(keyWords, default)

      englishKeyWords = "Trim-extend" + "/" + "No trim-extend"
      keyWords += "_" + englishKeyWords
      # si appresta ad attendere un punto o enter o una parola chiave o un numero reale     
      # msg, inputType, default, keyWords, nessun controllo
      self.waitFor(prompt, QadInputTypeEnum.KEYWORDS, default, \
                   keyWords)      


   #============================================================================
   # waitForSecondEntSel
   #============================================================================
   def waitForSecondEntSel(self):      
      self.step = 6      
      # imposto il map tool
      self.getPointMapTool().filletMode = self.filletMode
      self.getPointMapTool().radius = self.radius
      self.getPointMapTool().setEntityInfo(self.entity1.layer, self.entity1.featureId, self.linearObjectList1, \
                                           self.partAt1, self.pointAt1)      
      self.getPointMapTool().setMode(Qad_fillet_maptool_ModeEnum.ASK_FOR_SECOND_LINESTRING)

      # l'opzione Radius viene tradotta in italiano in "RAggio" nel contesto "waitForSecondEntSel"
      keyWords = QadMsg.translate("Command_FILLET", "Radius", "waitForSecondEntSel")           
      prompt = QadMsg.translate("Command_FILLET", "Select second object or shift-select to apply corner or [{0}]: ").format(keyWords)

      englishKeyWords = "Radius"
      keyWords += "_" + englishKeyWords
      # si appresta ad attendere un punto o enter o una parola chiave         
      # msg, inputType, default, keyWords, valore nullo non permesso
      self.waitFor(prompt, \
                   QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS, \
                   None, \
                   keyWords, QadInputModeEnum.NOT_NULL)      

        
   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
      
      if self.step == 0:
         CurrSettingsMsg = QadMsg.translate("QAD", "\nCurrent settings: ")
         if self.filletMode == 1:
            CurrSettingsMsg = CurrSettingsMsg + QadMsg.translate("Command_FILLET", "Mode = Trim-extend")
         else:
            CurrSettingsMsg = CurrSettingsMsg + QadMsg.translate("Command_FILLET", "Mode = No trim-extend")
               
         CurrSettingsMsg = CurrSettingsMsg + QadMsg.translate("Command_FILLET", ", Radius = ") + str(self.radius)
         self.showMsg(CurrSettingsMsg)         
            
         self.waitForFirstEntSel()
         return False # continua
      
      #=========================================================================
      # RISPOSTA ALLA SELEZIONE PRIMO OGGETTO
      elif self.step == 1:
         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
            else:
               value = self.getPointMapTool().point
         else: # il punto arriva come parametro della funzione
            value = msg

         if type(value) == unicode:
            if value == QadMsg.translate("Command_FILLET", "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.waitForFirstEntSel() # si appresta ad attendere la selezione del primo oggetto
            elif value == QadMsg.translate("Command_FILLET", "Polyline") or value == "Polyline":
               self.WaitForPolyline()
            # l'opzione Radius viene tradotta in italiano in "RAggio" nel contesto "waitForFirstEntSel"
            elif value == QadMsg.translate("Command_FILLET", "Radius", "waitForFirstEntSel") or value == "Radius":
               if self.GetDistClass is not None:
                  del self.GetDistClass
               self.GetDistClass = QadGetDistClass(self.plugIn)
               prompt = QadMsg.translate("Command_FILLET", "Specify fillet radius <{0}>: ")
               self.GetDistClass.msg = prompt.format(str(self.radius))
               self.GetDistClass.dist = self.radius
               self.GetDistClass.inputMode = QadInputModeEnum.NOT_NEGATIVE
               self.step = 3
               self.GetDistClass.run(msgMapTool, msg)
            elif value == QadMsg.translate("Command_FILLET", "Trim") or value == "Trim":
               self.waitForFilletMode()
            elif value == QadMsg.translate("Command_FILLET", "Multiple") or value == "Multiple":
               self.multi = True
               self.waitForFirstEntSel() # si appresta ad attendere la selezione del primo oggetto
                           
         elif type(value) == QgsPoint: # se é stato selezionato un punto
            self.entity1.clear()
            self.linearObjectList1.removeAll()            
            if self.getPointMapTool().entity.isInitialized():
               if self.setEntityInfo(True, self.getPointMapTool().entity.layer, \
                                     self.getPointMapTool().entity.featureId, value) == True:
                  self.waitForSecondEntSel() # si appresta ad attendere la selezione del secondo oggetto
                  return False
            else:
               # cerco se ci sono entità nel punto indicato considerando
               # solo layer lineari o poligono editabili che non appartengano a quote
               layerList = []
               for layer in qad_utils.getVisibleVectorLayers(self.plugIn.canvas): # Tutti i layer vettoriali visibili
                  if (layer.geometryType() == QGis.Line or layer.geometryType() == QGis.Polygon) and \
                     layer.isEditable():
                     if len(QadDimStyles.getDimListByLayer(layer)) == 0:
                        layerList.append(layer)
               
               result = qad_utils.getEntSel(self.getPointMapTool().toCanvasCoordinates(value), \
                                            self.getPointMapTool(), \
                                            layerList)
               if result is not None:
                  # result[0] = feature, result[1] = layer, result[0] = point
                  if self.setEntityInfo(True, result[1], result[0].id(), result[2]) == True:
                     self.waitForSecondEntSel() # si appresta ad attendere la selezione del secondo oggetto
                     return False
            self.waitForFirstEntSel() # si appresta ad attendere la selezione del primo oggetto                                    
         else:
            return True # fine comando
         
         return False 

      #=========================================================================
      # RISPOSTA ALLA SELEZIONE DI UNA POLILINEA (da step = 1)
      elif self.step == 2:
         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
            else:
               value = self.getPointMapTool().point
         else: # il punto arriva come parametro della funzione
            value = msg

         if type(value) == unicode:
            # l'opzione Radius viene tradotta in italiano in "Raggio" nel contesto "WaitForPolyline"
            if value == QadMsg.translate("Command_FILLET", "Radius", "WaitForPolyline") or value == "Radius":
               if self.GetDistClass is not None:
                  del self.GetDistClass
               self.GetDistClass = QadGetDistClass(self.plugIn)
               prompt = QadMsg.translate("Command_FILLET", "Specify fillet radius <{0}>: ")
               self.GetDistClass.msg = prompt.format(str(self.radius))
               self.GetDistClass.dist = self.radius
               self.GetDistClass.inputMode = QadInputModeEnum.NOT_NEGATIVE
               self.step = 5
               self.GetDistClass.run(msgMapTool, msg)                           
               return False
         elif type(value) == QgsPoint: # se é stato selezionato un punto
            self.entity1.clear()
            self.linearObjectList1.removeAll()            
            if self.getPointMapTool().entity.isInitialized():
               if self.setEntityInfo(True, self.getPointMapTool().entity.layer, \
                                     self.getPointMapTool().entity.featureId, value) == True:
                  if self.filletPolyline() == False or self.multi:
                     self.waitForFirstEntSel() # si appresta ad attendere la selezione del primo oggetto
                     return False
                  else:
                     return True
            else:
               # cerco se ci sono entità nel punto indicato considerando
               # solo layer lineari o poligono editabili che non appartengano a quote
               layerList = []
               for layer in qad_utils.getVisibleVectorLayers(self.plugIn.canvas): # Tutti i layer vettoriali visibili
                  if (layer.geometryType() == QGis.Line or layer.geometryType() == QGis.Polygon) and \
                     layer.isEditable():
                     if len(QadDimStyles.getDimListByLayer(layer)) == 0:
                        layerList.append(layer)

               result = qad_utils.getEntSel(self.getPointMapTool().toCanvasCoordinates(value), \
                                            self.getPointMapTool(), \
                                            QadVariables.get(QadMsg.translate("Environment variables", "PICKBOX")), \
                                            layerList)
               if result is not None:
                  # result[0] = feature, result[1] = layer, result[0] = point
                  if self.setEntityInfo(True, result[1], result[0].id(), result[2]) == True:
                     if self.filletPolyline() == False or self.multi:
                        self.waitForFirstEntSel() # si appresta ad attendere la selezione del primo oggetto
                        return False
                     else:
                        return True
         else:
            return True # fine comando

         self.WaitForPolyline()
         return False

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL RAGGIO DI RACCORDO (da step = 1)
      elif self.step == 3:
         if self.GetDistClass.run(msgMapTool, msg) == True:
            if self.GetDistClass.dist is not None:
               self.radius = self.GetDistClass.dist
               QadVariables.set(QadMsg.translate("Environment variables", "FILLETRAD"), self.radius)
               QadVariables.save()
            self.waitForFirstEntSel() # si appresta ad attendere la selezione del primo oggetto
            self.getPointMapTool().refreshSnapType() # aggiorno lo snapType che può essere variato dal maptool di distanza                     
         return False # fine comando
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DELLA MODALITA' DI TAGLIO (da step = 1)
      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
                  value = self.filletMode
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False
            else:
               value = self.getPointMapTool().point
         else: # il punto arriva come parametro della funzione
            value = msg

         if type(value) == unicode:
            if value == QadMsg.translate("Command_FILLET", "Trim-extend") or value == "Trim-extend":
               self.filletMode = 1
            elif value == QadMsg.translate("Command_FILLET", "No trim-extend") or value == "No trim-extend":
               self.filletMode = 2
            self.plugIn.setFilletMode(self.filletMode)
            
         self.waitForFirstEntSel() # si appresta ad attendere la selezione del primo oggetto
         return False
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL RAGGIO DI RACCORDO (da step = 3)
      elif self.step == 5:
         if self.GetDistClass.run(msgMapTool, msg) == True:
            if self.GetDistClass.dist is not None:
               self.radius = self.GetDistClass.dist
               QadVariables.set(QadMsg.translate("Environment variables", "FILLETRAD"), self.radius)
               QadVariables.save()
            self.WaitForPolyline()
            self.getPointMapTool().refreshSnapType() # aggiorno lo snapType che può essere variato dal maptool di distanza                     
         return False # fine comando
      
      #=========================================================================
      # RISPOSTA ALLA SELEZIONE SECONDO OGGETTO
      elif self.step == 6:
         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
            else:
               value = self.getPointMapTool().point
         else: # il punto arriva come parametro della funzione
            value = msg

         if type(value) == unicode:
            # l'opzione Radius viene tradotta in italiano in "RAggio" nel contesto "waitForSecondEntSel"
            if value == QadMsg.translate("Command_FILLET", "Radius", "waitForSecondEntSel") or value == "Radius":
               if self.GetDistClass is not None:
                  del self.GetDistClass
               self.GetDistClass = QadGetDistClass(self.plugIn)
               prompt = QadMsg.translate("Command_FILLET", "Specify fillet radius <{0}>: ")
               self.GetDistClass.msg = prompt.format(str(self.radius))
               self.GetDistClass.dist = self.radius
               self.GetDistClass.inputMode = QadInputModeEnum.NOT_NEGATIVE
               self.step = 7
               self.GetDistClass.run(msgMapTool, msg)
               return False
                           
         elif type(value) == QgsPoint: # se é stato selezionato un punto
            self.entity2.clear()
            self.linearObjectList2.removeAll()            

            if self.getPointMapTool().entity.isInitialized():
               if self.setEntityInfo(False, self.getPointMapTool().entity.layer, \
                                     self.getPointMapTool().entity.featureId, value) == True:
                  if self.getPointMapTool().shiftKey == True:
                     dummyRadius = self.radius
                     self.radius = 0
                     dummyFilletMode = self.filletMode
                     self.filletMode = 1 # modalità di raccordo; 1=Taglia-estendi
                     result = self.fillet()
                     self.radius = dummyRadius
                     self.filletMode = dummyFilletMode
                  else:
                     result = self.fillet()
                  
                  if result == False:
                     self.waitForSecondEntSel() # si appresta ad attendere la selezione del secondo oggetto         
                     return False 
                     
                  if self.multi:
                     self.waitForFirstEntSel() # si appresta ad attendere la selezione del primo oggetto
                     return False
                  else:
                     return True
            else:
               # cerco se ci sono entità nel punto indicato considerando
               # solo layer lineari o poligono editabili che non appartengano a quote
               layerList = []
               for layer in qad_utils.getVisibleVectorLayers(self.plugIn.canvas): # Tutti i layer vettoriali visibili
                  if (layer.geometryType() == QGis.Line or layer.geometryType() == QGis.Polygon) and \
                     layer.isEditable():
                     if len(QadDimStyles.getDimListByLayer(layer)) == 0:
                        layerList.append(layer)

               result = qad_utils.getEntSel(self.getPointMapTool().toCanvasCoordinates(value), \
                                            self.getPointMapTool(), \
                                            QadVariables.get(QadMsg.translate("Environment variables", "PICKBOX")), \
                                            layerList)
               if result is not None:
                  # result[0] = feature, result[1] = layer, result[0] = point
                  if self.setEntityInfo(False, result[1], result[0].id(), result[2]) == True:
                     if self.fillet() == False:
                        self.waitForSecondEntSel() # si appresta ad attendere la selezione del secondo oggetto         
                        return False 
               
                     if self.multi:
                        self.waitForFirstEntSel() # si appresta ad attendere la selezione del primo oggetto
                        return False
                     else:
                        return True
         else:
            return True # fine comando
         
         self.waitForSecondEntSel() # si appresta ad attendere la selezione del secondo oggetto         
         return False 

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL RAGGIO DI RACCORDO (da step = 6)
      elif self.step == 7:
         if self.GetDistClass.run(msgMapTool, msg) == True:
            if self.GetDistClass.dist is not None:
               self.radius = self.GetDistClass.dist
               QadVariables.set(QadMsg.translate("Environment variables", "FILLETRAD"), self.radius)
               QadVariables.save()      
            self.waitForSecondEntSel() # si appresta ad attendere la selezione del secondo oggetto
            self.getPointMapTool().refreshSnapType() # aggiorno lo snapType che può essere variato dal maptool di distanza                     
         return False # fine comando class QadPOLYGONCommandClass(QadCommandClass):

   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadPOLYGONCommandClass(self.plugIn)
   
   def getName(self):
      return QadMsg.translate("Command_list", "POLYGON")

   def getEnglishName(self):
      return "POLYGON"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runPOLYGONCommand)

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/polygon.png")

   def getNote(self):
      # impostare le note esplicative del comando
      return QadMsg.translate("Command_POLYGON", "Draws a regular polygon.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      # se questo flag = True il comando serve all'interno di un altro comando per disegnare un rettangolo
      # che non verrà salvato su un layer
      self.virtualCmd = False
      self.centerPt = None
      self.firstEdgePt = None
      self.vertices = []
      self.sideNumber = self.plugIn.lastPolygonSideNumber
      self.constructionModeByCenter = self.plugIn.lastPolygonConstructionModeByCenter
      self.area = 100

   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_polygon_maptool(self.plugIn)
         return self.PointMapTool
      else:
         return None       

      
   def addPolygonToLayer(self, layer):
      if layer.geometryType() == QGis.Line:
         qad_layer.addLineToLayer(self.plugIn, layer, self.vertices)
      elif layer.geometryType() == QGis.Polygon:                          
         qad_layer.addPolygonToLayer(self.plugIn, layer, self.vertices)
      

   #============================================================================
   # WaitForSideNumber
   #============================================================================
   def WaitForSideNumber(self):
      self.step = 1
      prompt = QadMsg.translate("Command_POLYGON", "Enter number of sides <{0}>: ")
      self.waitForInt(prompt.format(str(self.sideNumber)), self.sideNumber, \
                      QadInputModeEnum.NOT_ZERO | QadInputModeEnum.NOT_NEGATIVE)
         
   #============================================================================
   # WaitForCenter
   #============================================================================
   def WaitForCenter(self):
      self.step = 2
      self.getPointMapTool().setMode(Qad_polygon_maptool_ModeEnum.ASK_FOR_CENTER_PT)
      
      keyWords = QadMsg.translate("Command_POLYGON", "Edge")
      prompt = QadMsg.translate("Command_POLYGON", "Specify center of polygon or [{0}]: ").format(keyWords)
     
      englishKeyWords = "Edge"
      keyWords += "_" + englishKeyWords
      # si appresta ad attendere un punto o enter
      #                        msg, inputType,              default, keyWords, nessun controllo         
      self.waitFor(prompt, \
                   QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS, \
                   None, keyWords, QadInputModeEnum.NONE)
         
   #============================================================================
   # WaitForInscribedCircumscribedOption
   #============================================================================
   def WaitForInscribedCircumscribedOption(self):
      self.step = 3      
      keyWords = QadMsg.translate("Command_POLYGON", "Inscribed in circle") + "/" + \
                 QadMsg.translate("Command_POLYGON", "Circumscribed about circle") + "/" + \
                 QadMsg.translate("Command_POLYGON", "Area")
      prompt = QadMsg.translate("Command_POLYGON", "Enter an option [{0}] <{1}>: ").format(keyWords, \
                                                                                           self.constructionModeByCenter)

      englishKeyWords = "Inscribed in circle" + "/" + "Circumscribed about circle" + "/" + "Area"
      keyWords += "_" + englishKeyWords
      # si appresta ad attendere una parola chiave         
      # msg, inputType, default, keyWords, valori positivi
      self.waitFor(prompt, QadInputTypeEnum.KEYWORDS, \
                   self.constructionModeByCenter, \
                   keyWords, QadInputModeEnum.NONE)                  

   #============================================================================
   # WaitForRadius
   #============================================================================
   def WaitForRadius(self, layer):
      self.step = 4
      if layer is not None:
         self.getPointMapTool().geomType = layer.geometryType()
      self.getPointMapTool().setMode(Qad_polygon_maptool_ModeEnum.CENTER_PT_KNOWN_ASK_FOR_RADIUS)
      
      # si appresta ad attendere un punto o un numero reale         
      # msg, inputType, default, keyWords, valori positivi
      prompt = QadMsg.translate("Command_CIRCLE", "Specify the circle radius <{0}>: ")
      self.waitFor(prompt.format(str(self.plugIn.lastRadius)), \
                   QadInputTypeEnum.POINT2D | QadInputTypeEnum.FLOAT, \
                   self.plugIn.lastRadius, "", \
                   QadInputModeEnum.NOT_ZERO | QadInputModeEnum.NOT_NEGATIVE)

   #============================================================================
   # WaitForFirstEdgePt
   #============================================================================
   def WaitForFirstEdgePt(self):
      self.step = 5
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_polygon_maptool_ModeEnum.ASK_FOR_FIRST_EDGE_PT)
      # si appresta ad attendere un punto
      self.waitForPoint(QadMsg.translate("Command_POLYGON", "Specify the first point of the edge: "))

   #============================================================================
   # WaitForSecondEdgePt
   #============================================================================
   def WaitForSecondEdgePt(self, layer):
      self.step = 6
      self.getPointMapTool().firstEdgePt = self.firstEdgePt

      if layer is not None:
         self.getPointMapTool().geomType = layer.geometryType()

      # imposto il map tool
      self.getPointMapTool().setMode(Qad_polygon_maptool_ModeEnum.FIRST_EDGE_PT_KNOWN_ASK_FOR_SECOND_EDGE_PT)
      # si appresta ad attendere un punto
      self.waitForPoint(QadMsg.translate("Command_POLYGON", "Specify the second point of the edge: "))

   #============================================================================
   # WaitForArea
   #============================================================================
   def WaitForArea(self):
      self.step = 7
         
      msg = QadMsg.translate("Command_POLYGON", "Enter the polygon area in current units <{0}>: ")
      # si appresta ad attendere un numero reale         
      # msg, inputType, default, keyWords, valori positivi
      self.waitFor(msg.format(str(self.area)), QadInputTypeEnum.FLOAT, \
                   self.area, "", \
                   QadInputModeEnum.NOT_ZERO | QadInputModeEnum.NOT_NEGATIVE)

         
   #============================================================================
   # 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

      currLayer = None
      if self.virtualCmd == False: # se si vuole veramente salvare la polylinea in un layer   
         # il layer corrente deve essere editabile e di tipo linea o poligono
         currLayer, errMsg = qad_layer.getCurrLayerEditable(self.plugIn.canvas, [QGis.Line, QGis.Polygon])
         if currLayer is None:
            self.showErr(errMsg)
            return True # fine comando
      
      #=========================================================================
      # RICHIESTA NUMERO DI LATI DEL POLIGONO 
      if self.step == 0: # inizio del comando
         self.WaitForSideNumber()
         return False

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL NUMERO DI LATI DEL POLIGONO (da step = 0) 
      elif self.step == 1: # dopo aver atteso un punto si riavvia il comando
         if msgMapTool == True: # il punto arriva da una selezione grafica
            if self.getPointMapTool().rightButton == True: # se usato il tasto destro del mouse
               value = self.sideNumber
            else:
               return False
         else: # il punto arriva come parametro della funzione
            value = msg

         if type(value) == int:
            if value < 3:
               self.showErr(QadMsg.translate("Command_POLYGON", "\nEnter an integer greater than 2."))
            else:
               self.sideNumber = value
               self.getPointMapTool().sideNumber = self.sideNumber
               self.plugIn.setLastPolygonSideNumber(self.sideNumber)
               self.WaitForCenter()
         else:
            self.WaitForSideNumber()    

         return False # continua


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL CENTRO DEL POLIGONO (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.WaitForCenter()
                  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) == unicode:
            if value == QadMsg.translate("Command_POLYGON", "Edge") or value == "Edge":
               self.WaitForFirstEdgePt()
         elif type(value) == QgsPoint:
            self.centerPt = value
            self.getPointMapTool().centerPt = self.centerPt
            self.WaitForInscribedCircumscribedOption() 
                       
         return False # continua

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DI POLIGONO INSCRITTO O CIRCOSCRITTO (da step = 2)
      elif self.step == 3:
         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 = self.constructionModeByCenter
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False
            else:
               value = self.getPointMapTool().point
         else: # la parola chiave arriva come parametro della funzione
            value = msg        
         
         if type(value) == unicode:
            self.constructionModeByCenter = value
            self.plugIn.setLastPolygonConstructionModeByCenter(self.constructionModeByCenter)
            self.getPointMapTool().constructionModeByCenter = self.constructionModeByCenter
            if self.constructionModeByCenter == QadMsg.translate("Command_POLYGON", "Area") or self.constructionModeByCenter == "Area":
               self.WaitForArea()
            else:
               self.WaitForRadius(currLayer)
               
         return False # fine comando

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL RAGGIO (da step = 3)
      elif self.step == 4:
         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 il raggio del cerchio            
            if type(value) == QgsPoint: # se é stato inserito il raggio del cerchio con un punto                        
               self.radius = qad_utils.getDistance(self.centerPt, value)
               ptStart = value
            else:
               self.radius = value
               ptStart = None
               
            self.plugIn.setLastRadius(self.radius)     

            if self.constructionModeByCenter == QadMsg.translate("Command_POLYGON", "Inscribed in circle") or \
               self.constructionModeByCenter == "Inscribed in circle":
               mode = True
            else:
               mode = False
               
            self.vertices.extend(qad_utils.getPolygonByNsidesCenterRadius(self.sideNumber, self.centerPt, self.radius, \
                                                                          mode, ptStart))

            if self.virtualCmd == False: # se si vuole veramente salvare i buffer in un layer
               self.addPolygonToLayer(currLayer)
            return True       
         
         return False # fine comando
 
 
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL PRIMO PUNTO DELLO SPIGOLO (da step = 2)
      elif self.step == 5: # 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
                  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:
            self.firstEdgePt = value
            self.WaitForSecondEdgePt(currLayer)

         return False
            
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL SECONDO PUNTO DELLO SPIGOLO (da step = 5)
      elif self.step == 6: # 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:
            self.vertices.extend(qad_utils.getPolygonByNsidesEdgePts(self.sideNumber, self.firstEdgePt, value))

            if self.virtualCmd == False: # se si vuole veramente salvare i buffer in un layer
               self.addPolygonToLayer(currLayer)
            return True       

         return False


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA AREA POLIGONO (da step = 3)
      elif self.step == 7: # dopo aver atteso 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
                  value = self.area
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False
            else:
               return False
         else: # il punto arriva come parametro della funzione
            value = msg

         if type(value) == float: # é stata inserita l'area
            self.vertices.extend(qad_utils.getPolygonByNsidesArea(self.sideNumber, self.centerPt, value))

            if self.virtualCmd == False: # se si vuole veramente salvare i buffer in un layer
               self.addPolygonToLayer(currLayer)
            return True       
            
         return False class QadDIMLINEARCommandClass(QadCommandClass):

   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadDIMLINEARCommandClass(self.plugIn)
   
   def getName(self):
      return QadMsg.translate("Command_list", "DIMLINEAR")

   def getEnglishName(self):
      return "DIMLINEAR"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runDIMLINEARCommand)

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/dimLinear.png")

   def getNote(self):
      # impostare le note esplicative del comando
      return QadMsg.translate("Command_DIM", "Creates an horizontal or vertical linear dimension.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      self.entSelClass = None
      self.GetAngleClass = None
            
      self.dimPt1 = QgsPoint() # primo punto di quotatura esplicito
      self.dimPt2 = QgsPoint() # secondo punto di quotatura esplicito
      self.dimCircle = None    # oggetto cerchio da quotare
      
      self.measure = None # misura della quota (se None viene calcolato)
      self.preferredAlignment = QadDimStyleAlignmentEnum.HORIZONTAL # allineamento della linea di quota
      # leggo lo stile di quotatura corrente
      dimStyleName = QadVariables.get(QadMsg.translate("Environment variables", "DIMSTYLE"))
      self.forcedDimLineAlignment = None # allineamento della linea di quota forzato
      self.forcedDimLineRot = 0.0 # rotazione della linea di quota forzato
      
      _dimStyle = QadDimStyles.findDimStyle(dimStyleName)
      if _dimStyle is not None:
         self.dimStyle = QadDimStyle(_dimStyle) # ne faccio una copia perché può venire modificato dal comando
         self.dimStyle.dimType = QadDimTypeEnum.LINEAR
      else:
         self.dimStyle = None
      

   def __del__(self):
      QadCommandClass.__del__(self)
      if self.entSelClass is not None:
         self.entSelClass.entity.deselectOnLayer()
         del self.entSelClass
      if self.GetAngleClass is not None:
         del self.GetAngleClass


   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      if self.step == 2: # quando si é in fase di selezione entità
         return self.entSelClass.getPointMapTool(drawMode)
      # quando si é in fase di richiesta rotazione
      elif self.step == 6 or self.step == 7:
         return self.GetAngleClass.getPointMapTool()
      else:
         if (self.plugIn is not None):
            if self.PointMapTool is None:
               self.PointMapTool = Qad_dim_maptool(self.plugIn)
            return self.PointMapTool
         else:
            return None


   def getCurrentContextualMenu(self):
      if self.step == 2: # quando si é in fase di selezione entità
         return self.entSelClass.getCurrentContextualMenu()
      # quando si é in fase di richiesta rotazione
      elif self.step == 6 or self.step == 7:
         return self.GetAngleClass.getCurrentContextualMenu()
      else:
         return self.contextualMenu

   
   #============================================================================
   # addDimToLayers
   #============================================================================
   def addDimToLayers(self, linePosPt):
      return self.dimStyle.addLinearDimToLayers(self.plugIn, self.dimPt1, self.dimPt2, \
                                                linePosPt, self.measure, self.preferredAlignment, \
                                                self.forcedDimLineRot)
   
   
   #============================================================================
   # waitForFirstPt
   #============================================================================
   def waitForFirstPt(self):
      self.step = 1
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_dim_maptool_ModeEnum.NONE_KNOWN_ASK_FOR_FIRST_PT)                                

      msg = QadMsg.translate("Command_DIM", "Specify first extension line origin or <select object>: ")
      
      # si appresta ad attendere un punto o enter      
      # msg, inputType, default, keyWords, nessun controllo
      self.waitFor(msg, \
                   QadInputTypeEnum.POINT2D, \
                   None, \
                   "", QadInputModeEnum.NONE)

   
   #============================================================================
   # waitForSecondPt
   #============================================================================
   def waitForSecondPt(self):
      self.step = 3
      # imposto il map tool
      self.getPointMapTool().dimPt1 = self.dimPt1
      self.getPointMapTool().setMode(Qad_dim_maptool_ModeEnum.FIRST_PT_KNOWN_ASK_FOR_SECOND_PT)                                
      # si appresta ad attendere un punto
      self.waitForPoint(QadMsg.translate("Command_DIM", "Specify second extension line origin: "))

   
   #============================================================================
   # waitForEntsel
   #============================================================================
   def waitForEntsel(self, msgMapTool, msg):
      if self.entSelClass is not None:
         del self.entSelClass
      self.step = 2         
      self.entSelClass = QadEntSelClass(self.plugIn)
      self.entSelClass.msg = QadMsg.translate("Command_DIM", "Select the object to dimension: ")
      # scarto la selezione di punti
      self.entSelClass.checkPointLayer = False
      self.entSelClass.checkLineLayer = True
      self.entSelClass.checkPolygonLayer = True
      self.entSelClass.getPointMapTool().setSnapType(QadSnapTypeEnum.DISABLE)         
      self.entSelClass.run(msgMapTool, msg)

   
   #============================================================================
   # waitForDimensionLinePos
   #============================================================================
   def waitForDimensionLinePos(self):
      self.step = 4
      # imposto il map tool      
      self.getPointMapTool().dimPt2 = self.dimPt2
      if self.getPointMapTool().dimPt1 is None: # in caso di selezione oggetto dimPt1 non era stato inizializzato
         self.getPointMapTool().dimPt1 = self.dimPt1
         self.getPointMapTool().dimCircle = self.dimCircle
      self.getPointMapTool().preferredAlignment = self.preferredAlignment
      self.getPointMapTool().forcedDimLineAlignment = self.forcedDimLineAlignment
      self.getPointMapTool().forcedDimLineRot = self.forcedDimLineRot      
      self.getPointMapTool().dimStyle = self.dimStyle      
      self.getPointMapTool().setMode(Qad_dim_maptool_ModeEnum.FIRST_SECOND_PT_KNOWN_ASK_FOR_LINEAR_DIM_LINE_POS)                                
      
      # si appresta ad attendere un punto o una parola chiave
      keyWords = QadMsg.translate("Command_DIM", "Text") + "/" + \
                 QadMsg.translate("Command_DIM", "Angle") + "/" + \
                 QadMsg.translate("Command_DIM", "Horizontal") + "/" + \
                 QadMsg.translate("Command_DIM", "Vertical") + "/" + \
                 QadMsg.translate("Command_DIM", "Rotated")      
      prompt = QadMsg.translate("Command_DIM", "Specify dimension line location or [{0}]: ").format(keyWords)
      
      englishKeyWords = "Text" + "/" + "Angle" + "/" + "Horizontal" + "/" + "Vertical" + "/" + "Rotated"
      keyWords += "_" + englishKeyWords
      # msg, inputType, default, keyWords, nessun controllo
      self.waitFor(prompt, \
                   QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS, \
                   None, \
                   keyWords, \
                   QadInputModeEnum.NONE)                                      
      

   #============================================================================
   # 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

      if self.dimStyle is None:
         self.showMsg(QadMsg.translate("QAD", "\nDimension style not valid.\nVerify the value of DIMSTYLE variable.\n"))
         return True # fine comando
         
      errMsg = self.dimStyle.getInValidErrMsg()
      if errMsg is not None:
         self.showMsg(errMsg)
         return True # fine comando
      
      errMsg = self.dimStyle.getNotGraphEditableErrMsg()
      if errMsg is not None:
         self.showMsg(errMsg)
         return True # fine comando


      #=========================================================================
      # RICHIESTA SELEZIONE ORIGINE PRIMA LINEA DI ESTENSIONE
      if self.step == 0: # inizio del comando         
         self.waitForFirstPt()
         return False
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA ORIGINE PRIMA LINEA DI ESTENSIONE (da step = 0)
      elif self.step == 1:
         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 # opzione di default None
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False
            else:
               value = self.getPointMapTool().point
         else: # il punto arriva come parametro della funzione
            value = msg

         if value is None:
            self.waitForEntsel(msgMapTool, msg)
         else:
            self.dimPt1.set(value.x(), value.y())
            self.waitForSecondPt()

         return False

      #=========================================================================
      # RISPOSTA ALLA SELEZIONE DI UN'ENTITA' (da step = 1)
      elif self.step == 2:
         if self.entSelClass.run(msgMapTool, msg) == True:
            if self.entSelClass.entity.isInitialized():
               result = getStartEndPointClosestPartWithContext(self.entSelClass.entity, \
                                                               self.entSelClass.point, \
                                                               self.plugIn.canvas.mapSettings().destinationCrs())
               if result is not None:                   
                  if (type(result) == list or type(result) == tuple): # se é una lista di 2 punti
                     self.dimPt1 = result[0]                    
                     self.dimPt2 = result[1]
                  else:
                     objType = result.whatIs()
                     if objType == "ARC": # se é arco
                        self.dimPt1 = result.getStartPt()
                        self.dimPt2 = result.getEndPt()
                     elif objType == "CIRCLE": # se é cerchio
                        self.dimCircle = result
                  
               self.waitForDimensionLinePos()
               return False
            else:
               if self.entSelClass.canceledByUsr == True: # fine comando
                  return True
               self.showMsg(QadMsg.translate("QAD", "No geometries in this position."))
               self.waitForEntsel(msgMapTool, msg)
         return False # continua

         
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA ORIGINE SECONDA LINEA DI ESTENSIONE (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
               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 value is None:
            return True

         if type(value) == QgsPoint: # se é stato inserito il secondo punto
            self.dimPt2.set(value.x(), value.y())
            self.waitForDimensionLinePos()
         
         return False 
         
               
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DELLA POSIZIONE DELLA LINEA DI QUOTA (da step = 2 e 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) == unicode:
            if value == QadMsg.translate("Command_DIM", "Text") or value == "Text":
               prompt = QadMsg.translate("Command_DIM", "Enter dimension text <{0}>: ")
               dist = qad_utils.getDistance(self.dimPt1, self.dimPt2)
               self.waitForString(prompt.format(str(dist)), dist)
               self.getPointMapTool().setMode(Qad_dim_maptool_ModeEnum.ASK_FOR_TEXT)
               self.step = 5         
            elif value == QadMsg.translate("Command_DIM", "Angle") or value == "Angle":
               # si appresta ad attendere l'angolo di rotazione del testo
               if self.GetAngleClass is not None:
                  del self.GetAngleClass                                   
               self.GetAngleClass = QadGetAngleClass(self.plugIn)
               prompt = QadMsg.translate("Command_DIM", "Specify angle of dimension text <{0}>: ")
               self.GetAngleClass.msg = prompt.format(str(qad_utils.toDegrees(self.dimStyle.textForcedRot)))
               self.GetAngleClass.angle = self.dimStyle.textForcedRot
               self.step = 6
               self.GetAngleClass.run(msgMapTool, msg)               
            elif value == QadMsg.translate("Command_DIM", "Horizontal") or value == "Horizontal":
               # allineamento della linea di quota orizzontale
               self.forcedDimLineAlignment = QadDimStyleAlignmentEnum.HORIZONTAL # allineamento della linea di quota forzato               
               self.forcedDimLineRot = 0.0             
               self.waitForDimensionLinePos()
            elif value == QadMsg.translate("Command_DIM", "Vertical") or value == "Vertical":
               # allineamento della linea di quota verticale               
               self.forcedDimLineAlignment = QadDimStyleAlignmentEnum.VERTICAL # allineamento della linea di quota forzato
               self.forcedDimLineRot = 0.0             
               self.waitForDimensionLinePos()
            elif value == QadMsg.translate("Command_DIM", "Rotated") or value == "Rotated":
               # si appresta ad attendere l'angolo di rotazionedella linea di quotatura
               if self.GetAngleClass is not None:
                  del self.GetAngleClass                                   
               self.GetAngleClass = QadGetAngleClass(self.plugIn)
               prompt = QadMsg.translate("Command_DIM", "Specify angle of dimension line <{0}>: ")
               self.GetAngleClass.msg = prompt.format(str(qad_utils.toDegrees(self.forcedDimLineRot)))
               self.GetAngleClass.angle = self.forcedDimLineRot
               self.step = 7
               self.GetAngleClass.run(msgMapTool, msg)               
               pass
         elif type(value) == QgsPoint: # se é stato inserito il punto di posizionamento linea quota
            self.preferredAlignment = self.getPointMapTool().preferredAlignment
            self.dimPt1 = self.getPointMapTool().dimPt1
            self.dimPt2 = self.getPointMapTool().dimPt2
            self.addDimToLayers(value)
            return True # fine comando
            
         return False


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL TESTO (da step = 4)
      elif self.step == 5: # dopo aver atteso una stringa si riavvia il comando
         if type(msg) == unicode:
            text = msg.strip()
            if len(text) > 0:
               self.measure = text
               self.getPointMapTool().measure = self.measure
         self.waitForDimensionLinePos()
            
         return False
      
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA ROTAZIONE DEL TESTO DI QUOTA (da step = 4)
      elif self.step == 6:
         if self.GetAngleClass.run(msgMapTool, msg) == True:
            if self.GetAngleClass.angle is not None:
               self.dimStyle.textRotMode = QadDimStyleTxtRotModeEnum.FORCED_ROTATION
               self.dimStyle.textForcedRot = self.GetAngleClass.angle 
            self.waitForDimensionLinePos()

         return False
      
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA ROTAZIONE DELLA LINEA DI QUOTA (da step = 4)
      elif self.step == 7:
         if self.GetAngleClass.run(msgMapTool, msg) == True:
            if self.GetAngleClass.angle is not None:
               self.forcedDimLineRot = self.GetAngleClass.angle 
            self.waitForDimensionLinePos()

         return False class QadDIMALIGNEDCommandClass(QadCommandClass):
   
   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadDIMALIGNEDCommandClass(self.plugIn)
   
   def getName(self):
      return QadMsg.translate("Command_list", "DIMALIGNED")

   def getEnglishName(self):
      return "DIMALIGNED"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runDIMALIGNEDCommand)

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/dimAligned.png")

   def getNote(self):
      # impostare le note esplicative del comando
      return QadMsg.translate("Command_DIM", "Creates an aligned linear dimension.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      self.entSelClass = None
      self.GetAngleClass = None
      
      self.dimPt1 = QgsPoint()
      self.dimPt2 = QgsPoint()
      self.dimCircle = None    # oggetto cerchio da quotare
      
      self.measure = None # misura della quota (se None viene calcolato)
      # leggo lo stile di quotatura corrente
      dimStyleName = QadVariables.get(QadMsg.translate("Environment variables", "DIMSTYLE"))
      _dimStyle = QadDimStyles.findDimStyle(dimStyleName)      
      if _dimStyle is not None:
         self.dimStyle = QadDimStyle(_dimStyle) # ne faccio una copia perché può venire modificato dal comando
         self.dimStyle.dimType = QadDimTypeEnum.ALIGNED
      else:
         self.dimStyle = None
      

   def __del__(self):
      QadCommandClass.__del__(self)
      if self.entSelClass is not None:
         self.entSelClass.entity.deselectOnLayer()
         del self.entSelClass
      if self.GetAngleClass is not None:
         del self.GetAngleClass


   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      if self.step == 2: # quando si é in fase di selezione entità
         return self.entSelClass.getPointMapTool(drawMode)
      # quando si é in fase di richiesta rotazione
      elif self.step == 6:
         return self.GetAngleClass.getPointMapTool()
      else:
         if (self.plugIn is not None):
            if self.PointMapTool is None:
               self.PointMapTool = Qad_dim_maptool(self.plugIn)
            return self.PointMapTool
         else:
            return None


   def getCurrentContextualMenu(self):
      if self.step == 2: # quando si é in fase di selezione entità
         return self.entSelClass.getCurrentContextualMenu()
      # quando si é in fase di richiesta rotazione
      elif self.step == 6:
         return self.GetAngleClass.getCurrentContextualMenu()
      else:
         return self.contextualMenu

   
   #============================================================================
   # addDimToLayers
   #============================================================================
   def addDimToLayers(self, linePosPt):
      return self.dimStyle.addAlignedDimToLayers(self.plugIn, self.dimPt1, self.dimPt2, \
                                                 linePosPt, self.measure)

      
   #============================================================================
   # waitForFirstPt
   #============================================================================
   def waitForFirstPt(self):
      self.step = 1
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_dim_maptool_ModeEnum.NONE_KNOWN_ASK_FOR_FIRST_PT)                                

      msg = QadMsg.translate("Command_DIM", "Specify first extension line origin or <select object>: ")
      
      # si appresta ad attendere un punto o enter      
      # msg, inputType, default, keyWords, nessun controllo
      self.waitFor(msg, \
                   QadInputTypeEnum.POINT2D, \
                   None, \
                   "", QadInputModeEnum.NONE)

   
   #============================================================================
   # waitForSecondPt
   #============================================================================
   def waitForSecondPt(self):
      self.step = 3
      # imposto il map tool
      self.getPointMapTool().dimPt1 = self.dimPt1
      self.getPointMapTool().setMode(Qad_dim_maptool_ModeEnum.FIRST_PT_KNOWN_ASK_FOR_SECOND_PT)                                
      # si appresta ad attendere un punto
      self.waitForPoint(QadMsg.translate("Command_DIM", "Specify second extension line origin: "))

   
   #============================================================================
   # waitForEntsel
   #============================================================================
   def waitForEntsel(self, msgMapTool, msg):
      if self.entSelClass is not None:
         del self.entSelClass
      self.step = 2         
      self.entSelClass = QadEntSelClass(self.plugIn)
      self.entSelClass.msg = QadMsg.translate("Command_DIM", "Select the object to dimension: ")
      # scarto la selezione di punti
      self.entSelClass.checkPointLayer = False
      self.entSelClass.checkLineLayer = True
      self.entSelClass.checkPolygonLayer = True
      self.entSelClass.getPointMapTool().setSnapType(QadSnapTypeEnum.DISABLE)         
      self.entSelClass.run(msgMapTool, msg)

   
   #============================================================================
   # waitForDimensionLinePos
   #============================================================================
   def waitForDimensionLinePos(self):
      self.step = 4
      # imposto il map tool      
      self.getPointMapTool().dimPt2 = self.dimPt2
      if self.getPointMapTool().dimPt1 is None: # in caso di selezione oggetto dimPt1 non era stato inizializzato
         self.getPointMapTool().dimPt1 = self.dimPt1
         self.getPointMapTool().dimCircle = self.dimCircle
      self.getPointMapTool().dimStyle = self.dimStyle      
      self.getPointMapTool().setMode(Qad_dim_maptool_ModeEnum.FIRST_SECOND_PT_KNOWN_ASK_FOR_ALIGNED_DIM_LINE_POS)                                
      
      # si appresta ad attendere un punto o una parola chiave
      keyWords = QadMsg.translate("Command_DIM", "Text") + "/" + \
                 QadMsg.translate("Command_DIM", "Angle")      
      prompt = QadMsg.translate("Command_DIM", "Specify dimension line location or [{0}]: ").format(keyWords)
      englishKeyWords = "Text" + "/" + "Angle"
      keyWords += "_" + englishKeyWords
      
      # msg, inputType, default, keyWords, nessun controllo
      self.waitFor(prompt, \
                   QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS, \
                   None, \
                   keyWords, \
                   QadInputModeEnum.NONE)                                      
      

   #============================================================================
   # 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

      if self.dimStyle is None:
         self.showMsg(QadMsg.translate("QAD", "\nDimension style not valid.\nVerify the value of DIMSTYLE variable.\n"))
         return True # fine comando
         
      errMsg = self.dimStyle.getInValidErrMsg()
      if errMsg is not None:
         self.showMsg(errMsg)
         return True # fine comando
      
      errMsg = self.dimStyle.getNotGraphEditableErrMsg()
      if errMsg is not None:
         self.showMsg(errMsg)
         return True # fine comando


      #=========================================================================
      # RICHIESTA SELEZIONE ORIGINE PRIMA LINEA DI ESTENSIONE
      if self.step == 0: # inizio del comando         
         self.waitForFirstPt()
         return False
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA ORIGINE PRIMA LINEA DI ESTENSIONE (da step = 0)
      elif self.step == 1:
         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 # opzione di default None
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False
            else:
               value = self.getPointMapTool().point
         else: # il punto arriva come parametro della funzione
            value = msg

         if value is None:
            self.waitForEntsel(msgMapTool, msg)
         else:
            self.dimPt1.set(value.x(), value.y())
            self.waitForSecondPt()

         return False

      #=========================================================================
      # RISPOSTA ALLA SELEZIONE DI UN'ENTITA' (da step = 1)
      elif self.step == 2:
         if self.entSelClass.run(msgMapTool, msg) == True:
            if self.entSelClass.entity.isInitialized():
               result = getStartEndPointClosestPartWithContext(self.entSelClass.entity, \
                                                               self.entSelClass.point, \
                                                               self.plugIn.canvas.mapSettings().destinationCrs())
               if result is not None:
                  if (type(result) == list or type(result) == tuple): # se é una lista di 2 punti
                     self.dimPt1 = result[0]                    
                     self.dimPt2 = result[1]
                  else:
                     objType = result.whatIs()
                     if objType == "ARC": # se é arco
                        self.dimPt1 = result.getStartPt()                 
                        self.dimPt2 = result.getEndPt()
                     elif objType == "CIRCLE": # se é cerchio
                        self.dimCircle = result
                        intPts = self.dimCircle.getIntersectionPointsWithInfinityLine(self.dimCircle.center, self.entSelClass.point)
                        if len(intPts) == 2:
                           self.dimPt1 = intPts[0]
                           self.dimPt2 = intPts[1]                     
                  
               self.waitForDimensionLinePos()
               return False
            else:
               if self.entSelClass.canceledByUsr == True: # fine comando
                  return True
               self.showMsg(QadMsg.translate("QAD", "No geometries in this position."))
               self.waitForEntsel(msgMapTool, msg)
         return False # continua


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA ORIGINE SECONDA LINEA DI ESTENSIONE (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
               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 value is None:
            return True

         if type(value) == QgsPoint: # se é stato inserito il secondo punto
            self.dimPt2.set(value.x(), value.y())
            self.waitForDimensionLinePos()
         
         return False 
         
               
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DELLA POSIZIONE DELLA LINEA DI QUOTA (da step = 2 e 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) == unicode:
            if value == QadMsg.translate("Command_DIM", "Text") or value == "Text":
               prompt = QadMsg.translate("Command_DIM", "Enter dimension text <{0}>: ")
               dist = qad_utils.getDistance(self.dimPt1, self.dimPt2)
               self.waitForString(prompt.format(str(dist)), dist)
               self.getPointMapTool().setMode(Qad_dim_maptool_ModeEnum.ASK_FOR_TEXT)
               self.step = 5         
            elif value == QadMsg.translate("Command_DIM", "Angle") or value == "Angle":
               # si appresta ad attendere l'angolo di rotazione del testo
               if self.GetAngleClass is not None:
                  del self.GetAngleClass                                   
               self.GetAngleClass = QadGetAngleClass(self.plugIn)
               prompt = QadMsg.translate("Command_DIM", "Specify angle of dimension text <{0}>: ")
               self.GetAngleClass.msg = prompt.format(str(qad_utils.toDegrees(self.dimStyle.textForcedRot)))
               self.GetAngleClass.angle = self.dimStyle.textForcedRot
               self.step = 6
               self.GetAngleClass.run(msgMapTool, msg)               
         elif type(value) == QgsPoint: # se é stato inserito il punto di posizionamento linea quota
            self.dimPt1 = self.getPointMapTool().dimPt1
            self.dimPt2 = self.getPointMapTool().dimPt2
            self.addDimToLayers(value)
            return True # fine comando
            
         return False


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL TESTO (da step = 4)
      elif self.step == 5: # dopo aver atteso una stringa si riavvia il comando
         if type(msg) == unicode:
            text = msg.strip()
            if len(text) > 0:
               self.measure = text
               self.getPointMapTool().measure = self.measure
         self.waitForDimensionLinePos()
            
         return False


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA ROTAZIONE DEL TESTO DI QUOTA (da step = 4)
      elif self.step == 6:
         if self.GetAngleClass.run(msgMapTool, msg) == True:
            if self.GetAngleClass.angle is not None:
               self.dimStyle.textRotMode = QadDimStyleTxtRotModeEnum.FORCED_ROTATION
               self.dimStyle.textForcedRot = self.GetAngleClass.angle 
            self.waitForDimensionLinePos()

         return False class QadDIMARCCommandClass(QadCommandClass):

   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadDIMARCCommandClass(self.plugIn)
   
   def getName(self):
      return QadMsg.translate("Command_list", "DIMARC")

   def getEnglishName(self):
      return "DIMARC"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runDIMARCCommand)

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/dimArc.png")

   def getNote(self):
      # impostare le note esplicative del comando
      return QadMsg.translate("Command_DIM", "Creates an arc length dimension.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      self.entSelClass = None
      self.GetAngleClass = None
      self.dimPt1 = QgsPoint()
      self.dimPt2 = QgsPoint()
      self.dimArc = None    # oggetto arco da quotare
      self.dimPartialArc = QadArc()
      self.leader = False # opzione disponibile solo per archi > 90 gradi 
            
      self.measure = None # misura della quota (se None viene calcolato)
      # leggo lo stile di quotatura corrente
      dimStyleName = QadVariables.get(QadMsg.translate("Environment variables", "DIMSTYLE"))
      self.dimStyle = QadDimStyles.findDimStyle(dimStyleName)
      if self.dimStyle is not None:
         self.dimStyle.dimType = QadDimTypeEnum.ARC_LENTGH
      

   def __del__(self):
      QadCommandClass.__del__(self)
      if self.entSelClass is not None:
         self.entSelClass.entity.deselectOnLayer()
         del self.entSelClass
      if self.GetAngleClass is not None:
         del self.GetAngleClass


   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      if self.step == QadDIMARCCommandClassStepEnum.ASK_FOR_ENTSEL: # quando si é in fase di selezione entità
         return self.entSelClass.getPointMapTool(drawMode)
      # quando si é in fase di richiesta rotazione
      elif self.step == QadDIMARCCommandClassStepEnum.ASK_FOR_TEXT_ROT:
         return self.GetAngleClass.getPointMapTool()
      else:
         if (self.plugIn is not None):
            if self.PointMapTool is None:
               self.PointMapTool = Qad_dim_maptool(self.plugIn)
            return self.PointMapTool
         else:
            return None


   def getCurrentContextualMenu(self):
      if self.step == QadDIMARCCommandClassStepEnum.ASK_FOR_ENTSEL: # quando si é in fase di selezione entità
         return self.entSelClass.getCurrentContextualMenu()
      # quando si é in fase di richiesta rotazione
      elif self.step == QadDIMARCCommandClassStepEnum.ASK_FOR_TEXT_ROT:
         return self.GetAngleClass.getCurrentContextualMenu()
      else:
         return self.contextualMenu


   #============================================================================
   # setArc
   #============================================================================
   def setArc(self, entity, point):
      """
      Setta self.dimArc che definisce l'arco da quotare
      """      
      geom = self.layerToMapCoordinates(entity.layer, entity.getGeometry())
      obj = qad_utils.whatGeomIs(point, geom)
      if (obj is None):
         return False
      if obj.whatIs() == "ARC":
         self.dimArc = obj
         self.dimPartialArc.set(self.dimArc.center, self.dimArc.radius, self.dimArc.startAngle, self.dimArc.endAngle)
         return True
      else:
         return False


   #============================================================================
   # getPartialPtOnArc
   #============================================================================
   def getPartialPtOnArc(self, pt):
      """
      calcola il punto sull'arco più vicino a pt che è un punto scelto dall'utente
      """      
      perpPts = self.dimArc.getPerpendicularPoints(pt)
      if len(perpPts) == 0: # cerco il punto più vicino a pt1 tra quello iniziale e finale
         startPt = self.dimArc.getStartPt()
         endPt = self.dimArc.getEndPt()
         if qad_utils.getDistance(startPt, pt) <= qad_utils.getDistance(endPt, pt):
            return startPt
         else:
            return endPt
      elif len(perpPts) == 1:
         return perpPts[0]
      elif len(perpPts) == 2: # cerco il punto più vicino a pt1
         if qad_utils.getDistance(perpPts[0], pt) <= qad_utils.getDistance(perpPts[1], pt):
            return perpPts[0]
         else:
            return perpPts[1]

      return None


   #============================================================================
   # setPartialArc
   #============================================================================
   def setPartialArc(self):
      """
      Calcola l'arco parziale di dimArc che ha i punti finali in dimPt1 e dimPt2
      """
      self.dimPartialArc.setEndAngleByPt(self.dimPt1)
      l1 = self.dimPartialArc.length()
      self.dimPartialArc.setEndAngleByPt(self.dimPt2)
      l2 = self.dimPartialArc.length()
      
      if l1 > l2: # se dimPt1 è più lontano di dimPt2 dal punto iniziale dell'arco
         self.dimPartialArc.setEndAngleByPt(self.dimPt1)
         self.dimPartialArc.setStartAngleByPt(self.dimPt2)
      else: # se dimPt1 è più vicino di dimPt2 dal punto iniziale dell'arco
         self.dimPartialArc.setStartAngleByPt(self.dimPt1)


   #============================================================================
   # addDimToLayers
   #============================================================================
   def addDimToLayers(self, linePosPt):
      return self.dimStyle.addArcDimToLayers(self.plugIn, self.dimPartialArc, \
                                             linePosPt, self.measure, self.leader)

   
   #============================================================================
   # waitForEntsel
   #============================================================================
   def waitForEntsel(self, msgMapTool, msg):
      if self.entSelClass is not None:
         del self.entSelClass
      self.step = QadDIMARCCommandClassStepEnum.ASK_FOR_ENTSEL
      self.entSelClass = QadEntSelClass(self.plugIn)
      self.entSelClass.msg = QadMsg.translate("Command_DIM", "Select arc or polyline arc segment: ")
      # scarto la selezione di punti e delle quote
      self.entSelClass.checkPointLayer = False
      self.entSelClass.checkLineLayer = True
      self.entSelClass.checkPolygonLayer = True
      self.entSelClass.checkDimLayers = False
      self.entSelClass.getPointMapTool().setSnapType(QadSnapTypeEnum.DISABLE)
      self.entSelClass.run(msgMapTool, msg)

   
   #============================================================================
   # waitForDimensionLinePos
   #============================================================================
   def waitForDimensionLinePos(self):
      self.step = QadDIMARCCommandClassStepEnum.ASK_FOR_MAIN_OPTIONS
      # imposto il map tool      
      self.getPointMapTool().dimArc = self.dimPartialArc
      self.getPointMapTool().dimStyle = self.dimStyle
      self.getPointMapTool().setMode(Qad_dim_maptool_ModeEnum.FIRST_SECOND_PT_KNOWN_ASK_FOR_ARC_DIM_LINE_POS)
      
      # si appresta ad attendere un punto o una parola chiave
      # si appresta ad attendere un punto o una parola chiave
      keyWords = QadMsg.translate("Command_DIM", "Text") + "/" + \
                 QadMsg.translate("Command_DIM", "Angle") + "/" + \
                 QadMsg.translate("Command_DIM", "Partial") + "/"
      englishKeyWords = "Text" + "/" + "Angle" + "/" + "Partial"
      
      # se l'angolo dell'arco è > 90 gradi si usa anche l'opzione direttrice
      if self.dimArc.totalAngle() > math.pi:
         if self.leader == False:
            keyWords = keyWords + QadMsg.translate("Command_DIM", "Leader")
            englishKeyWords = englishKeyWords + "/" + "Leader"
         else:
            keyWords = keyWords + QadMsg.translate("Command_DIM", "No leader")
            englishKeyWords = englishKeyWords + "/" + "No leader"
         
      prompt = QadMsg.translate("Command_DIM", "Specify dimension location or [{0}]: ").format(keyWords)
      keyWords += "_" + englishKeyWords

      # msg, inputType, default, keyWords, nessun controllo
      self.waitFor(prompt, \
                   QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS, \
                   None, \
                   keyWords, \
                   QadInputModeEnum.NONE)                                      
      

   #============================================================================
   # waitForFirstPt
   #============================================================================
   def waitForFirstPt(self):
      self.step = QadDIMARCCommandClassStepEnum.ASK_FOR_1PT_ARC
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_dim_maptool_ModeEnum.ASK_FOR_PARTIAL_ARC_PT_FOR_DIM_ARC)

      msg = QadMsg.translate("Command_DIM", "Specify first point on the arc: ")
      
      # si appresta ad attendere un punto
      self.waitForPoint(msg)
      

   #============================================================================
   # waitForSecondPt
   #============================================================================
   def waitForSecondPt(self):
      self.step = QadDIMARCCommandClassStepEnum.ASK_FOR_2PT_ARC
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_dim_maptool_ModeEnum.ASK_FOR_PARTIAL_ARC_PT_FOR_DIM_ARC)

      msg = QadMsg.translate("Command_DIM", "Specify second point on the arc: ")
      
      # si appresta ad attendere un punto
      self.waitForPoint(msg)


   #============================================================================
   # 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

      if self.dimStyle is None:
         self.showMsg(QadMsg.translate("QAD", "\nDimension style not valid.\nVerify the value of DIMSTYLE variable.\n"))
         return True # fine comando
         
      errMsg = self.dimStyle.getInValidErrMsg()
      if errMsg is not None:
         self.showMsg(errMsg)
         return True # fine comando
      
      errMsg = self.dimStyle.getNotGraphEditableErrMsg()
      if errMsg is not None:
         self.showMsg(errMsg)
         return True # fine comando

      if self.step == QadDIMARCCommandClassStepEnum.START:
         self.waitForEntsel(msgMapTool, msg)
         return False # continua

      #=========================================================================
      # RISPOSTA ALLA SELEZIONE DI UN'ENTITA'
      if self.step == QadDIMARCCommandClassStepEnum.ASK_FOR_ENTSEL:
         if self.entSelClass.run(msgMapTool, msg) == True:
            if self.entSelClass.entity.isInitialized():
               if self.setArc(self.entSelClass.entity, self.entSelClass.point) == True:
                  self.waitForDimensionLinePos()
               else:
                  self.showMsg(QadMsg.translate("Command_DIM", "Select an arc or polyline arc segment."))
            else:               
               if self.entSelClass.canceledByUsr == True: # fine comando
                  return True
               self.showMsg(QadMsg.translate("QAD", "No geometries in this position."))
               self.waitForEntsel(msgMapTool, msg)
         return False # continua


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DELLA POSIZIONE DELLA LINEA DI QUOTA
      elif self.step == QadDIMARCCommandClassStepEnum.ASK_FOR_MAIN_OPTIONS: # dopo aver atteso un punto o una opzione 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) == unicode:
            if value == QadMsg.translate("Command_DIM", "Text") or value == "Text":
               prompt = QadMsg.translate("Command_DIM", "Enter dimension text <{0}>: ")
               dist = self.dimPartialArc.length()
               self.waitForString(prompt.format(str(dist)), dist)
               self.getPointMapTool().setMode(Qad_dim_maptool_ModeEnum.ASK_FOR_TEXT)
               self.step = QadDIMARCCommandClassStepEnum.ASK_FOR_TEXT_VALUE
            elif value == QadMsg.translate("Command_DIM", "Angle") or value == "Angle":
               # si appresta ad attendere l'angolo di rotazione del testo
               if self.GetAngleClass is not None:
                  del self.GetAngleClass                                   
               self.GetAngleClass = QadGetAngleClass(self.plugIn)
               prompt = QadMsg.translate("Command_DIM", "Specify angle of dimension text <{0}>: ")
               self.GetAngleClass.msg = prompt.format(str(qad_utils.toDegrees(self.dimStyle.textForcedRot)))
               self.GetAngleClass.angle = self.dimStyle.textForcedRot
               self.step = QadDIMARCCommandClassStepEnum.ASK_FOR_TEXT_ROT
               self.GetAngleClass.run(msgMapTool, msg)
            elif value == QadMsg.translate("Command_DIM", "Partial") or value == "Partial":
               self.waitForFirstPt()
            elif value == QadMsg.translate("Command_DIM", "Leader") or value == "Leader":
               self.leader = True
               self.waitForDimensionLinePos()
            elif value == QadMsg.translate("Command_DIM", "No leader") or value == "No leader":
               self.leader = False
               self.waitForDimensionLinePos()
               
         elif type(value) == QgsPoint: # se é stato inserito il punto di posizionamento linea quota
            self.addDimToLayers(value)
            return True # fine comando
            
         return False


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL TESTO (da step = ASK_FOR_MAIN_OPTIONS)
      elif self.step == QadDIMARCCommandClassStepEnum.ASK_FOR_TEXT_VALUE: # dopo aver atteso una stringa si riavvia il comando
         if type(msg) == unicode:
            text = msg.strip()
            if len(text) > 0:
               self.measure = text
               self.getPointMapTool().measure = self.measure
         self.waitForDimensionLinePos()
            
         return False
      
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA ROTAZIONE DEL TESTO DI QUOTA (da step = ASK_FOR_MAIN_OPTIONS)
      elif self.step == QadDIMARCCommandClassStepEnum.ASK_FOR_TEXT_ROT:
         if self.GetAngleClass.run(msgMapTool, msg) == True:
            if self.GetAngleClass.angle is not None:
               self.dimStyle.textRotMode = QadDimStyleTxtRotModeEnum.FORCED_ROTATION
               self.dimStyle.textForcedRot = self.GetAngleClass.angle 
            self.waitForDimensionLinePos()

         return False
      

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL PRIMO PUNTO SULL'ARCO (da step = ASK_FOR_MAIN_OPTIONS)
      elif self.step == QadDIMARCCommandClassStepEnum.ASK_FOR_1PT_ARC: # 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
               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 secondo punto
            ptOnArc = self.getPartialPtOnArc(value)
            if ptOnArc is not None:
               self.dimPt1.set(ptOnArc.x(), ptOnArc.y())

         self.waitForSecondPt()
         
         return False 
      

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL PRIMO PUNTO SULL'ARCO (da step = ASK_FOR_1PT_ARC)
      elif self.step == QadDIMARCCommandClassStepEnum.ASK_FOR_2PT_ARC: # 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
               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 secondo punto
            ptOnArc = self.getPartialPtOnArc(value)
            if ptOnArc is not None:
               self.dimPt2.set(ptOnArc.x(), ptOnArc.y())
            
            self.setPartialArc()
            self.waitForDimensionLinePos()
         
         return False  class QadDIMSTYLECommandClass(QadCommandClass):
   
   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadDIMSTYLECommandClass(self.plugIn)
   
   def getName(self):
      return QadMsg.translate("Command_list", "DIMSTYLE")

   def getEnglishName(self):
      return "DIMSTYLE"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runDIMSTYLECommand)

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/dimStyle.png")

   def getNote(self):
      # impostare le note esplicative del comando
      return QadMsg.translate("Command_DIMSTYLE", "Creates new styles, sets the current style, modifies styles, sets overrides on the current style, and compares styles.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
            
   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
      Form = QadDIMSTYLEDialog(self.plugIn)
      Form.exec_()
      return True class QadLENGTHENCommandClass(QadCommandClass):

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

   def getName(self):
      return QadMsg.translate("Command_list", "LENGTHEN")

   def getEnglishName(self):
      return "LENGTHEN"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runLENGTHENCommand)

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/lengthen.png")
   
   def getNote(self):
      # impostare le note esplicative del comando      
      return QadMsg.translate("Command_LENGTHEN", "Lengthen an object.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      self.OpMode = plugIn.lastOpMode_lengthen # "DElta" o "Percent" o "Total" o "DYnamic"
      self.OpType = None # "length" o "Angle"
      self.value = None 

      self.startPt = None
      self.GetDistClass = None
      self.GetAngleClass = None
      self.entity = QadEntity()
      self.linearObjectList = None
      self.atSubGeom = None
      self.move_startPt = None
      
      self.nOperationsToUndo = 0


   def __del__(self):
      QadCommandClass.__del__(self)
      if self.GetDistClass is not None:
         del self.GetDistClass      
      if self.GetAngleClass is not None:
         del self.GetAngleClass


   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      if self.step == 3: # quando si é in fase di richiesta distanza
         return self.GetDistClass.getPointMapTool()
      if self.step == 4: # quando si é in fase di richiesta angolo
         return self.GetAngleClass.getPointMapTool()
      elif (self.plugIn is not None):
         if self.PointMapTool is None:
            self.PointMapTool = Qad_lengthen_maptool(self.plugIn)
         return self.PointMapTool
      else:
         return None


   def getCurrentContextualMenu(self):
      if self.step == 3: # quando si é in fase di richiesta distanza
         return self.GetDistClass.getCurrentContextualMenu()
      if self.step == 4: # quando si é in fase di richiesta angolo
         return self.GetAngleClass.getCurrentContextualMenu()
      else:
         return self.contextualMenu


   def setInfo(self, entity, point):
      # setta: self.entity, self.linearObjectList, self.atSubGeom e self.move_startPt
      if self.linearObjectList is not None:
         del self.linearObjectList
         self.linearObjectList = None
      
      self.entity.set(entity.layer, entity.featureId)
      transformedPt = self.mapToLayerCoordinates(self.entity.layer, point)
      f = self.entity.getFeature()
      geom = self.entity.getGeometry()
                  
      # ritorna una tupla (<The squared cartesian distance>,
      #                    <minDistPoint>
      #                    <afterVertex>
      #                    <leftOf>)
      res = False
      dummy = qad_utils.closestSegmentWithContext(transformedPt, 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(), transformedPt) <= \
         qad_utils.getDistance(self.linearObjectList.getEndPt(), transformedPt):
         # si allunga dal punto iniziale
         self.move_startPt = True
      else:
         # si allunga dal punto finale
         self.move_startPt = False
         
      return True
   

   #============================================================================
   # lengthen
   #============================================================================
   def lengthen(self, point):
      layer = self.entity.layer
      f = self.entity.getFeature()
      if f is None: # non c'è più la feature
         return False
      geom = self.entity.getGeometry()
                  
      # ritorna una tupla (<The squared cartesian distance>,
      #                    <minDistPoint>
      #                    <afterVertex>
      #                    <leftOf>)
      res = False
      if self.OpMode == "DElta":
         newLinearObjectList = qad_utils.QadLinearObjectList(self.linearObjectList)
         if self.OpType == "length":
            res = newLinearObjectList.lengthen_delta(self.move_startPt, self.value)
         elif self.OpType == "Angle":
            res = newLinearObjectList.lengthen_deltaAngle(self.move_startPt, self.value)
      elif self.OpMode == "Percent":
         newLinearObjectList = qad_utils.QadLinearObjectList(self.linearObjectList)
         value = newLinearObjectList.length() * self.value / 100
         value = value - newLinearObjectList.length()
         res = newLinearObjectList.lengthen_delta(self.move_startPt, value)
      elif self.OpMode == "Total":
         newLinearObjectList = qad_utils.QadLinearObjectList(self.linearObjectList)
         if self.OpType == "length":
            value = self.value - newLinearObjectList.length()
            res = newLinearObjectList.lengthen_delta(self.move_startPt, value)
         elif self.OpType == "Angle":                     
            if newLinearObjectList.qty() == 1:
               linearObject = newLinearObjectList.getLinearObjectAt(0)
               if linearObject.isArc() == True: # se è un arco
                  value = self.value - linearObject.getArc().totalAngle()
                  res = newLinearObjectList.lengthen_deltaAngle(self.move_startPt, value)
      elif self.OpMode == "DYnamic":
         newLinearObjectList = qad_utils.QadLinearObjectList(self.linearObjectList)
         transformedPt = self.mapToLayerCoordinates(layer, point)
            
         if self.move_startPt:
            linearObject = newLinearObjectList.getLinearObjectAt(0)
         else:
            linearObject = newLinearObjectList.getLinearObjectAt(-1)
            
         if linearObject.isSegment():
            newPt = qad_utils.getPerpendicularPointOnInfinityLine(linearObject.getStartPt(), linearObject.getEndPt(), transformedPt)
         else: # arco
            newPt = qad_utils.getPolarPointByPtAngle(linearObject.getArc().center, \
                                                     qad_utils.getAngleBy2Pts(linearObject.getArc().center, transformedPt), \
                                                     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
      f.setGeometry(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()
      self.nOperationsToUndo = self.nOperationsToUndo + 1
      
      return True


   
   def showLength(self, entity, pt):
      # visualizza la lunghezza dell'entità in unità di mappa
      geom = entity.getGeometry()
      if geom is None:         
         errMsg = QadMsg.translate("QAD", "Invalid object.")
         self.showErr("\n" + errMsg)
         return None
   
      # Trasformo il punto nel sistema di coordinate del layer
      convPt = self.mapToLayerCoordinates(entity.layer, pt)

      # ritorna una tupla (<The squared cartesian distance>,
      #                    <minDistPoint>
      #                    <afterVertex>
      #                    <leftOf>)
      dummy = qad_utils.closestSegmentWithContext(pt, geom)
      if dummy[2] is None:
         errMsg = QadMsg.translate("QAD", "Invalid object.")
         self.showErr("\n" + errMsg)
         return None
      # ritorna la sotto-geometria al vertice <atVertex> e la sua posizione nella geometria (0-based)
      subGeom, atSubGeom = qad_utils.getSubGeomAtVertex(geom, dummy[2])
      
      LinearObjectListToMisure = qad_utils.QadLinearObjectList()
      pointList = subGeom.asPolyline()
      LinearObjectListToMisure.fromPolyline(pointList)
      # la trasformo in unità di mappa
      LinearObjectListToMisure.transformFromCRSToCRS(entity.layer.crs(), self.plugIn.canvas.mapSettings().destinationCrs())      
      
      msg = QadMsg.translate("Command_LENGTHEN", "\nCurrent length: {0}")
      msg = msg.format(str(LinearObjectListToMisure.length()))

      arc = QadArc()
      startEndVertices = arc.fromPolyline(pointList, 0)
      # se la polilinea è composta solo da un arco
      if startEndVertices and startEndVertices[0] == 0 and startEndVertices[1] == len(pointList)-1:
         msg = msg + QadMsg.translate("Command_LENGTHEN", ", included angle: {0}")
         msg = msg.format(str(qad_utils.toDegrees(arc.totalAngle())))
         
      self.showMsg(msg)


   def waitForObjectSelToMisure(self):
      self.step = 1      
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_lengthen_maptool_ModeEnum.ASK_FOR_OBJ_TO_MISURE)

      if self.plugIn.lastOpMode_lengthen == "DElta":
         self.defaultValue = QadMsg.translate("Command_LENGTHEN", "DElta")
      elif self.plugIn.lastOpMode_lengthen == "Percent":
         self.defaultValue = QadMsg.translate("Command_LENGTHEN", "Percent")
      elif self.plugIn.lastOpMode_lengthen == "Total":
         self.defaultValue = QadMsg.translate("Command_LENGTHEN", "Total")
      elif self.plugIn.lastOpMode_lengthen == "DYnamic":
         self.defaultValue = QadMsg.translate("Command_LENGTHEN", "DYnamic")
      else:
         self.defaultValue = None
      
      keyWords = QadMsg.translate("Command_LENGTHEN", "DElta") + "/" + \
                 QadMsg.translate("Command_LENGTHEN", "Percent") + "/" + \
                 QadMsg.translate("Command_LENGTHEN", "Total") + "/" + \
                 QadMsg.translate("Command_LENGTHEN", "DYnamic")
      if self.defaultValue is None:
         prompt = QadMsg.translate("Command_LENGTHEN", "Select an object or [{0}] <{1}>:  ").format(keyWords, self.defaultValue)
      else:
         prompt = QadMsg.translate("Command_LENGTHEN", "Select an object or [{0}] <{1}>:  ").format(keyWords, self.defaultValue)

      englishKeyWords = "DElta" + "/" + "Percent" + "/" + "Total" + "/" + "DYnamic"
      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, \
                   self.defaultValue, \
                   keyWords, QadInputModeEnum.NONE)


   def waitForDelta(self):
      self.step = 2
      self.OpMode = "DElta"
      self.plugIn.setLastOpMode_lengthen(self.OpMode)
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_lengthen_maptool_ModeEnum.ASK_FOR_DELTA)

      keyWords = QadMsg.translate("Command_LENGTHEN", "Angle")
      prompt = QadMsg.translate("Command_LENGTHEN", "Enter delta length or [{0}] <{1}>: ").format(keyWords, str(self.plugIn.lastDelta_lengthen))

      englishKeyWords = "Angle"
      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 | QadInputTypeEnum.FLOAT, \
                   self.plugIn.lastDelta_lengthen, \
                   keyWords, QadInputModeEnum.NONE)
      

   def waitForDeltaLength(self, msgMapTool, msg):
      self.step = 3
      self.OpType = "length"

      # si appresta ad attendere una distanza                     
      if self.GetDistClass is not None:
         del self.GetDistClass
      self.GetDistClass = QadGetDistClass(self.plugIn)     
      prompt = QadMsg.translate("Command_LENGTHEN", "Enter delta length <{0}>: ")
      self.GetDistClass.msg = prompt.format(str(self.plugIn.lastDelta_lengthen))
      self.GetDistClass.startPt = self.startPt
      self.GetDistClass.dist = self.plugIn.lastDelta_lengthen
      self.GetDistClass.inputMode = QadInputModeEnum.NONE
      self.GetDistClass.run(msgMapTool, msg)


   def waitForDeltaAngle(self, msgMapTool, msg):
      self.step = 4
      self.OpType = "Angle"

      # si appresta ad attendere l'angolo di rotazione                      
      if self.GetAngleClass is not None:
         del self.GetAngleClass                  
      self.GetAngleClass = QadGetAngleClass(self.plugIn)
      prompt = QadMsg.translate("Command_LENGTHEN", "Enter delta angle <{0}>: ")
      self.GetAngleClass.msg = prompt.format(str(qad_utils.toDegrees(self.plugIn.lastDeltaAngle_lengthen)))
      self.GetAngleClass.angle = self.plugIn.lastDeltaAngle_lengthen
      self.GetAngleClass.run(msgMapTool, msg)         


   def waitForObjectSel(self):
      self.step = 5
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_lengthen_maptool_ModeEnum.ASK_FOR_OBJ_TO_LENGTHEN)
      self.getPointMapTool().refreshSnapType() # aggiorno lo snapType che può essere variato dal maptool di distanza o angolo
      self.getPointMapTool().OpType = self.OpType 
      self.getPointMapTool().value = self.value

      keyWords = QadMsg.translate("Command_LENGTHEN", "Undo")
      prompt = QadMsg.translate("Command_LENGTHEN", "Select an object to change or [{0}]: ").format(QadMsg.translate("Command_LENGTHEN", "Undo"))

      englishKeyWords = "Undo"
      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)


   def waitForPercent(self):
      self.step = 6
      self.OpMode = "Percent"
      self.plugIn.setLastOpMode_lengthen(self.OpMode)

      # imposto il map tool
      self.getPointMapTool().setMode(Qad_lengthen_maptool_ModeEnum.ASK_FOR_PERCENT)

      prompt = QadMsg.translate("Command_LENGTHEN", "Enter percentage length <{0}>: ")
      prompt = prompt.format(str(self.plugIn.lastPerc_lengthen))
      # si appresta ad attendere un numero reale         
      # msg, inputType, default, keyWords, valori positivi
      self.waitFor(prompt, QadInputTypeEnum.FLOAT, \
                   self.plugIn.lastPerc_lengthen, "", \
                   QadInputModeEnum.NOT_ZERO | QadInputModeEnum.NOT_NEGATIVE)

 
   def waitForTotal(self):
      self.step = 7
      self.OpMode = "Total"
      self.plugIn.setLastOpMode_lengthen(self.OpMode)
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_lengthen_maptool_ModeEnum.ASK_FOR_TOTAL)

      keyWords = QadMsg.translate("Command_LENGTHEN", "Angle")
      prompt = QadMsg.translate("Command_LENGTHEN", "Specify total length or [{0}] <{1}>: ").format(keyWords, str(self.plugIn.lastTotal_lengthen))

      englishKeyWords = "Angle"
      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 | QadInputTypeEnum.FLOAT, \
                   self.plugIn.lastTotal_lengthen, \
                   keyWords, QadInputModeEnum.NOT_ZERO | QadInputModeEnum.NOT_NEGATIVE)
      

   def waitForTotalLength(self, msgMapTool, msg):
      self.step = 8
      self.OpType = "length"

      # si appresta ad attendere una distanza                     
      if self.GetDistClass is not None:
         del self.GetDistClass
      self.GetDistClass = QadGetDistClass(self.plugIn)     
      prompt = QadMsg.translate("Command_LENGTHEN", "Enter total length <{0}>: ")
      self.GetDistClass.msg = prompt.format(str(self.plugIn.lastTotal_lengthen))
      self.GetDistClass.startPt = self.startPt
      self.GetDistClass.dist = self.plugIn.lastTotal_lengthen
      self.GetDistClass.inputMode = QadInputModeEnum.NONE
      self.GetDistClass.run(msgMapTool, msg)


   def waitForTotalAngle(self, msgMapTool, msg):
      self.step = 9
      self.OpType = "Angle"

      # si appresta ad attendere l'angolo di rotazione                      
      if self.GetAngleClass is not None:
         del self.GetAngleClass                  
      self.GetAngleClass = QadGetAngleClass(self.plugIn)
      prompt = QadMsg.translate("Command_LENGTHEN", "Enter total angle <{0}>: ")
      self.GetAngleClass.msg = prompt.format(str(qad_utils.toDegrees(self.plugIn.lastTotalAngle_lengthen)))
      self.GetAngleClass.angle = self.plugIn.lastTotalAngle_lengthen
      self.GetAngleClass.run(msgMapTool, msg)         


   def waitForDynamicPt(self):
      self.step = 10
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_lengthen_maptool_ModeEnum.ASK_FOR_DYNAMIC_POINT)

      prompt = QadMsg.translate("Command_LENGTHEN", "Specify new endpoint: ")

      # si appresta ad attendere un punto o enter o una parola chiave         
      # msg, inputType, default, keyWords, nessun controllo
      self.waitFor(prompt, \
                   QadInputTypeEnum.POINT2D, \
                   None, \
                   "", QadInputModeEnum.NONE)


   #============================================================================
   # 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
         # si appresta ad attendere la selezione degli oggetti da estendere/tagliare
         self.waitForObjectSelToMisure()
         return False

      #=========================================================================
      # RISPOSTA ALLA SELEZIONE OGGETTI DA MISURARE
      elif self.step == 1:
         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 = self.defaultValue
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False
            else:
               value = self.getPointMapTool().point
         else: # il punto arriva come parametro della funzione
            value = msg

         if type(value) == unicode:
            if value == QadMsg.translate("Command_LENGTHEN", "DElta") or value == "DElta":
               self.waitForDelta()
               return False
            elif value == QadMsg.translate("Command_LENGTHEN", "Percent") or value == "Percent":
               self.waitForPercent()
               return False
            elif value == QadMsg.translate("Command_LENGTHEN", "Total") or value == "Total":
               self.waitForTotal()
               return False
            elif value == QadMsg.translate("Command_LENGTHEN", "DYnamic") or value == "DYnamic":
               self.OpMode = "DYnamic"
               self.plugIn.setLastOpMode_lengthen(self.OpMode)
               # si appresta ad attendere la selezione degli oggetti da allungare
               self.waitForObjectSel()
               return False

         elif type(value) == QgsPoint: # se é stato selezionato un punto
            if self.getPointMapTool().entity.isInitialized():
               self.showLength(self.getPointMapTool().entity, value)
            else:
               # cerco se ci sono entità nel punto indicato considerando
               # solo layer di tipo lineari che non appartengano a quote o di tipo poligono 
               layerList = []
               for layer in qad_utils.getVisibleVectorLayers(self.plugIn.canvas): # Tutti i layer vettoriali visibili
                  if layer.geometryType() == QGis.Line or layer.geometryType() == QGis.Polygon:
                     if len(QadDimStyles.getDimListByLayer(layer)) == 0:
                        layerList.append(layer)
                                     
               result = qad_utils.getEntSel(self.getPointMapTool().toCanvasCoordinates(value), \
                                            self.getPointMapTool(), \
                                            QadVariables.get(QadMsg.translate("Environment variables", "PICKBOX")), \
                                            layerList)
               if result is not None:
                  feature = result[0]
                  layer = result[1]
                  self.showLength(QadEntity().set(layer, feature.id()), value)
         else:
            return True # fine comando
         
         # si appresta ad attendere la selezione degli oggetti da misurare
         self.waitForObjectSelToMisure()
                                          
         return False


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL DELTA (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
                  value = self.plugIn.lastDelta_lengthen # opzione di default "spostamento"
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False
            else:
               value = self.getPointMapTool().point
         else: # il punto arriva come parametro della funzione
            value = msg

         if type(value) == unicode:
            if value == QadMsg.translate("Command_LENGTHEN", "Angle") or value == "Angle":
               self.waitForDeltaAngle(msgMapTool, msg)
         elif type(value) == QgsPoint: # se é stato inserito un punto
            self.startPt = value
            self.waitForDeltaLength(msgMapTool, msg)
         elif type(value) == float: # se é stato inserito il delta
            self.plugIn.setLastDelta_lengthen(value)
            self.OpType = "length"
            self.value = value
            # si appresta ad attendere la selezione degli oggetti da allungare
            self.waitForObjectSel()

         return False 


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DELLA LUNGHEZZA DEL DELTA (da step = 2)
      elif self.step == 3: # dopo aver atteso un punto o un numero reale si riavvia il comando
         if self.GetDistClass.run(msgMapTool, msg) == True:
            if self.GetDistClass.dist is not None:
               self.plugIn.setLastDelta_lengthen(self.GetDistClass.dist)
               self.value = self.GetDistClass.dist
               # si appresta ad attendere la selezione degli oggetti da allungare
               self.waitForObjectSel()
               

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DELL'ANGOLO DEL DELTA (da step = 2)
      elif self.step == 4: # dopo aver atteso un punto o un numero reale si riavvia il comando
         if self.GetAngleClass.run(msgMapTool, msg) == True:
            if self.GetAngleClass.angle is not None:
               self.plugIn.setLastDeltaAngle_lengthen(self.GetAngleClass.angle)
               self.value = self.GetAngleClass.angle
               # si appresta ad attendere la selezione degli oggetti da allungare
               self.waitForObjectSel()


      #=========================================================================
      # RISPOSTA ALLA SELEZIONE OGGETTI DA ALLUNGARE
      elif self.step == 5:
         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
            else:
               value = self.getPointMapTool().point
         else: # il punto arriva come parametro della funzione
            value = msg

         if type(value) == unicode:
            if value == QadMsg.translate("Command_LENGTHEN", "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."))                  
         elif type(value) == QgsPoint: # se é stato selezionato un punto
            if self.getPointMapTool().entity.isInitialized():
               self.setInfo(self.getPointMapTool().entity, value)
               if self.OpMode != "DYnamic":
                  self.lengthen(value)
               else:
                  self.waitForDynamicPt()
                  return False
            else:
               # cerco se ci sono entità nel punto indicato considerando
               # solo layer lineari editabili che non appartengano a quote
               layerList = []
               for layer in qad_utils.getVisibleVectorLayers(self.plugIn.canvas): # Tutti i layer vettoriali visibili
                  if layer.geometryType() == QGis.Line and layer.isEditable():
                     if len(QadDimStyles.getDimListByLayer(layer)) == 0:
                        layerList.append(layer)
                                     
               result = qad_utils.getEntSel(self.getPointMapTool().toCanvasCoordinates(value), \
                                            self.getPointMapTool(), \
                                            QadVariables.get(QadMsg.translate("Environment variables", "PICKBOX")), \
                                            layerList)
               if result is not None:
                  feature = result[0]
                  layer = result[1]
                  self.setInfo(QadEntity().set(layer, feature.id()), value)

                  if self.OpMode != "DYnamic":
                     self.lengthen(value)
                  else:
                     self.waitForDynamicPt()
                     return False
         else:
            return True # fine comando

         # si appresta ad attendere la selezione degli oggetti da allungare
         self.waitForObjectSel()
                           
         return False 

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA PERCENTUALE (da step = 1)
      elif self.step == 6: # dopo aver atteso 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
                  value = self.plugIn.lastPerc_lengthen
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False
            else:
               return False
         else: # il punto arriva come parametro della funzione
            value = msg

         if type(value) == float: # é stata inserita la percentuale
            self.plugIn.setLastPerc_lengthen(value)
            self.value = value
            # si appresta ad attendere la selezione degli oggetti da allungare
            self.waitForObjectSel()
            
         return False


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL TOTALE (da step = 1)
      elif self.step == 7: # 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
                  value = self.plugIn.lastTotal_lengthen
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False
            else:
               value = self.getPointMapTool().point
         else: # il punto arriva come parametro della funzione
            value = msg

         if type(value) == unicode:
            if value == QadMsg.translate("Command_LENGTHEN", "Angle") or value == "Angle":
               self.waitForTotalAngle(msgMapTool, msg)
         elif type(value) == QgsPoint: # se é stato inserito un punto
            self.startPt = value
            self.waitForTotalLength(msgMapTool, msg)
         elif type(value) == float: # se é stato inserito il delta
            self.plugIn.setLastTotal_lengthen(value)
            self.OpType = "length"
            self.value = value
            # si appresta ad attendere la selezione degli oggetti da allungare
            self.waitForObjectSel()

         return False 


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DELLA LUNGHEZZA DEL TOTALE (da step = 7)
      elif self.step == 8: # dopo aver atteso un punto o un numero reale si riavvia il comando
         if self.GetDistClass.run(msgMapTool, msg) == True:
            if self.GetDistClass.dist is not None:
               self.plugIn.setLastTotal_lengthen(self.GetDistClass.dist)
               self.value = self.GetDistClass.dist
               # si appresta ad attendere la selezione degli oggetti da allungare
               self.waitForObjectSel()
               return False
            

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DELL'ANGOLO DEL DELTA (da step = 7)
      elif self.step == 9: # dopo aver atteso un punto o un numero reale si riavvia il comando
         if self.GetAngleClass.run(msgMapTool, msg) == True:
            if self.GetAngleClass.angle is not None:
               self.plugIn.setLastTotalAngle_lengthen(self.GetAngleClass.angle)
               self.value = self.GetAngleClass.angle
               # si appresta ad attendere la selezione degli oggetti da allungare
               self.waitForObjectSel()
               return False


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DELLA NUOVA ESTREMITA' IN MODO DINAMICO (da step = 5)
      elif self.step == 10: # 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
               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 un punto
            self.lengthen(value)
            
         # si appresta ad attendere la selezione degli oggetti da allungare
         self.waitForObjectSel()
            
         return False class QadHELPCommandClass(QadCommandClass):

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

   def getName(self):
      return QadMsg.translate("Command_list", "HELP")

   def getEnglishName(self):
      return "HELP"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runHELPCommand)

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/help.png")

   def getNote(self):
      # impostare le note esplicative del comando
      return QadMsg.translate("Command_HELP", "The QAD manual will be showed.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
        
   def run(self, msgMapTool = False, msg = None):
      qadShowPluginHelp()       
      return True class QadOPTIONSCommandClass(QadCommandClass):
   
   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadOPTIONSCommandClass(self.plugIn)
   
   def getName(self):
      return QadMsg.translate("Command_list", "OPTIONS")

   def getEnglishName(self):
      return "OPTIONS"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runOPTIONSCommand)

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/options.png")

   def getNote(self):
      # impostare le note esplicative del comando
      return QadMsg.translate("Command_OPTIONS", "QAD Options.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
            
   def run(self, msgMapTool = False, msg = None):
      Form = QadOPTIONSDialog(self.plugIn)
      Form.exec_()
      return True class QadMAPMPEDITCommandClass(QadCommandClass):

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

   def getName(self):
      return QadMsg.translate("Command_list", "MAPMPEDIT")
   
   def getEnglishName(self):
      return "MAPMPEDIT"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runMAPMPEDITCommand)

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/mapmpedit.png")
   
   def getNote(self):
      # impostare le note esplicative del comando      
      return QadMsg.translate("Command_MAPMPEDIT", "Modifies existing polygon.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      
      self.poligonEntity = QadEntity()
      
      self.SSGetClass = QadSSGetClass(plugIn)
      self.SSGetClass.onlyEditableLayers = False
      self.SSGetClass.checkDimLayers = False # scarto le quote
      
      self.entSelClass = None
      
      self.currSubGeom = None
      self.currAtSubGeom = None
     
      self.nOperationsToUndo = 0
   
   def __del__(self):
      QadCommandClass.__del__(self)
      del self.SSGetClass
      self.poligonEntity.deselectOnLayer()

   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      if self.step == 1 or self.step == 4: # quando si é in fase di selezione entità
         return self.entSelClass.getPointMapTool(drawMode)
      elif self.step == 3 or self.step == 5 or \
           self.step == 6 or self.step == 7 or self.step == 8: # quando si é in fase di selezione gruppo entità
         return self.SSGetClass.getPointMapTool()           
      else:
         return QadCommandClass.getPointMapTool(self, drawMode)


   def getCurrentContextualMenu(self):
      if self.step == 1 or self.step == 4: # quando si é in fase di selezione entità
         return self.entSelClass.getCurrentContextualMenu()
      elif self.step == 3 or self.step == 5 or \
           self.step == 6 or self.step == 7 or self.step == 8: # quando si é in fase di selezione gruppo entità
         return self.SSGetClass.getCurrentContextualMenu()           
      else:
         return self.contextualMenu


   def reinitSSGetClass(self):
      checkPointLayer = self.SSGetClass.checkPointLayer
      del self.SSGetClass
      self.SSGetClass = QadSSGetClass(self.plugIn)
      self.SSGetClass.onlyEditableLayers = False
      self.SSGetClass.checkDimLayers = False # scarto le quote
      self.SSGetClass.checkPointLayer = checkPointLayer


   #============================================================================
   # setCurrentSubGeom
   #============================================================================
   def setCurrentSubGeom(self, entSelClass):
      """
      Setta la sottogeometria corrente
      """
      self.currSubGeom = None
      self.currAtSubGeom = None

      # verifico che sia stata selezionata un'entità
      if entSelClass.entity.isInitialized() == False:
         self.showMsg(QadMsg.translate("QAD", "No geometries in this position."))
         return False
      # verifico che sia stata selezionata attraverso un punto
      # (per capire quale sottogeometria è stata selezionata)
      if entSelClass.point is None: return False
      # verifico che sia stato selezionato lo stesso polygono che è da modificare
      if self.poligonEntity != entSelClass.entity:
         self.showMsg(QadMsg.translate("Command_MAPMPEDIT", "The boundary doesn't belong to the selected polygon."))
         return False
      
      # trasformo la geometria nel crs del canvas per lavorare con coordinate piane xy
      geom = self.layerToMapCoordinates(entSelClass.entity.layer, entSelClass.entity.getGeometry())
      
      # ritorna una tupla (<The squared cartesian distance>,
      #                    <minDistPoint>
      #                    <afterVertex>
      #                    <leftOf>)
      dummy = qad_utils.closestSegmentWithContext(entSelClass.point, geom)
      if dummy[2] is None:
         return False
      # ritorna la sotto-geometria al vertice <atVertex> e la sua posizione nella geometria (0-based)
      self.currSubGeom, self.currAtSubGeom = qad_utils.getSubGeomAtVertex(geom, dummy[2])
      if self.currSubGeom is None or self.currAtSubGeom is None:
         self.currSubGeom = None
         self.currAtSubGeom = None
         return False
      
      return True
   

   #============================================================================
   # addEntitySetToPolygon
   #============================================================================
   def addEntitySetToPolygon(self, entitySet, removeOriginals = False):
      """
      Aggiunge il set di entità al poligono da modificare
      """
      geom = self.poligonEntity.getGeometry()
      layerList = []
      layerList.append(self.poligonEntity.layer)
      
      for layerEntitySet in entitySet.layerEntitySetList:
         layer = layerEntitySet.layer
         if layer.geometryType() != QGis.Polygon and layer.geometryType() != QGis.Line:
            self.showMsg(QadMsg.translate("QAD", "Invalid object."))
            return False

         if removeOriginals: layerList.append(layer)
         coordTransform = QgsCoordinateTransform(layer.crs(), self.poligonEntity.layer.crs())

         for featureId in layerEntitySet.featureIds:
            # se la feature è quella di polygonEntity è errore 
            if layer.id() == self.poligonEntity.layerId() and featureId == self.poligonEntity.featureId:
               self.showMsg(QadMsg.translate("QAD", "Invalid object."))
               return False
            
            f = layerEntitySet.getFeature(featureId)
            # trasformo la geometria nel crs del layer del poligono da modificare
            geomToAdd = f.geometry()
            geomToAdd.transform(coordTransform)
            
            # se il poligono è contenuto nella geometria da aggiungere
            if geomToAdd.contains(geom):
               # Riduco la geometria in point o polyline
               simplifiedGeoms = qad_utils.asPointOrPolyline(geom)
               # deve essere un poligono senza ring
               if len(simplifiedGeoms) != 1 or simplifiedGeoms[0].wkbType() != QGis.WKBLineString:
                  self.showMsg(QadMsg.translate("QAD", "Invalid object."))
                  return False
               points = simplifiedGeoms[0].asPolyline() # vettore di punti
               # aggiungo un'isola
               if geomToAdd.addRing(points) != 0: # 0 in case of success
                  self.showMsg(QadMsg.translate("QAD", "Invalid object."))
                  return False
               del geom
               geom = QgsGeometry.fromPolygon(geomToAdd.asPolygon())
            else: # se il poligono non è contenuto nella geometria da aggiungere
               # Riduco la geometria in point o polyline
               simplifiedGeoms = qad_utils.asPointOrPolyline(geomToAdd)
               for simplifiedGeom in simplifiedGeoms:
                  points = simplifiedGeom.asPolyline() # vettore di punti                     
                  # se la geometria da aggiungere è contenuta nel poligono
                  if geom.contains(QgsGeometry.fromPolyline(points)):
                     # aggiungo un'isola
                     if geom.addRing(points) != 0: # 0 in case of success
                        self.showMsg(QadMsg.translate("QAD", "Invalid object."))
                        return False
                  else:
                     # aggiungo una parte
                     if geom.addPart(points) != 0: # 0 in case of success
                        self.showMsg(QadMsg.translate("QAD", "Invalid object."))
                        return False

      f = self.poligonEntity.getFeature()
      f.setGeometry(geom)

      layerList = entitySet.getLayerList()
      layerList.append(self.poligonEntity.layer)

      self.plugIn.beginEditCommand("Feature edited", layerList)
         
      # plugIn, layer, feature, refresh, check_validity
      if qad_layer.updateFeatureToLayer(self.plugIn, self.poligonEntity.layer, f, False, False) == False:
         self.plugIn.destroyEditCommand()
         return False

      if removeOriginals:
         for layerEntitySet in entitySet.layerEntitySetList:            
            if qad_layer.deleteFeaturesToLayer(self.plugIn, layerEntitySet.layer, layerEntitySet.featureIds, False) == False:
               self.plugIn.destroyEditCommand()
               return 

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

      return True
   

   #============================================================================
   # delCurrentSubGeomToPolygon
   #============================================================================
   def delCurrentSubGeomToPolygon(self):
      """
      Cancella la sotto-geometria corrente dal poligono da modificare
      """
      geom = self.poligonEntity.getGeometry()

       # la posizione é espressa con una lista (<index ogg. princ> [<index ogg. sec.>])
      part = self.currAtSubGeom[0]
      if len(self.currAtSubGeom) == 2:
         ring = self.currAtSubGeom[1]
         if geom.deleteRing(ring + 1, part) == False: # cancello una isola (Ring 0 is outer ring and can't be deleted)
            self.showMsg(QadMsg.translate("QAD", "Invalid object."))
            return False
      else:
         if geom.deletePart(part) == False: # cancello una parte
            self.showMsg(QadMsg.translate("QAD", "Invalid object."))
            return False

      f = self.poligonEntity.getFeature()
      f.setGeometry(geom)

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

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


   #============================================================================
   # unionIntersSubtractEntitySetToPolygon
   #============================================================================
   def unionIntersSubtractEntitySetToPolygon(self, entitySet, opType, removeOriginals = False):
      """
      Unisce o interseca i poligoni di entitySet al poligono corrente
      """
      geom = self.poligonEntity.getGeometry()
      layerList = []
      layerList.append(self.poligonEntity.layer)
      
      geomList = []
      geomList.append(geom)
      for layerEntitySet in entitySet.layerEntitySetList:
         del geomList[:]
         layer = layerEntitySet.layer
         coordTransform = QgsCoordinateTransform(layer.crs(), self.poligonEntity.layer.crs())
         
         if layer.geometryType() == QGis.Polygon:
            for featureId in layerEntitySet.featureIds:
               # se la feature è quella di polygonEntity è errore 
               if layer.id() == self.poligonEntity.layerId() and featureId == self.poligonEntity.featureId:
                  self.showMsg(QadMsg.translate("QAD", "Invalid object."))
                  return False
               f = layerEntitySet.getFeature(featureId)
               # trasformo la geometria nel crs del layer del poligono da modificare
               geomToAdd = f.geometry()

               geomToAdd.transform(coordTransform)

               if opType == QadMAPMPEDITCommandOpTypeEnum.UNION: geom = geom.combine(geomToAdd)
               elif opType == QadMAPMPEDITCommandOpTypeEnum.INTERSECTION: geom = geom.intersection(geomToAdd)
               elif opType == QadMAPMPEDITCommandOpTypeEnum.DIFFERENCE: geom = geom.difference(geomToAdd)
               
               if geom is None:
                  self.showMsg(QadMsg.translate("QAD", "Invalid object."))
                  return False
               
               if removeOriginals and layer.id() != self.poligonEntity.layerId():
                  layerList.append(layer)

         elif layer.geometryType() == QGis.Line:
            for featureId in layerEntitySet.featureIds:
               f = layerEntitySet.getFeature(featureId)
               # trasformo la geometria nel crs del layer del poligono da modificare
               geomToAdd = f.geometry()
               geomToAdd.transform(coordTransform)
               # Riduco la geometria in point o polyline
               simplifiedGeoms = qad_utils.asPointOrPolyline(geomToAdd)
               for simplifiedGeom in simplifiedGeoms:
                  if simplifiedGeom.wkbType() != QGis.WKBLineString:
                     self.showMsg(QadMsg.translate("QAD", "Invalid object."))
                     return False
                  points = simplifiedGeom.asPolyline() # vettore di punti
                  
                  if len(points) < 4 or points[0] != points[-1]: # polilinea chiusa con almeno 4 punti (primo e ultimo uguali)
                     self.showMsg(QadMsg.translate("QAD", "Invalid object."))
                     return False
                  geomToAdd = QgsGeometry.fromPolygon([points])
                  
                  if opType == QadMAPMPEDITCommandOpTypeEnum.UNION: geom = geom.combine(geomToAdd)
                  elif opType == QadMAPMPEDITCommandOpTypeEnum.INTERSECTION: geom = geom.intersection(geomToAdd)
                  elif opType == QadMAPMPEDITCommandOpTypeEnum.DIFFERENCE: geom = geom.difference(geomToAdd)
                  
                  if geom is None or geom.type() != QGis.Polygon:
                     self.showMsg(QadMsg.translate("QAD", "Invalid object."))
                     return False
                  
               if removeOriginals: layerList.append(layer)
         else:
            self.showMsg(QadMsg.translate("QAD", "Invalid object."))
            return False

      f = self.poligonEntity.getFeature()
      f.setGeometry(geom)

      self.plugIn.beginEditCommand("Feature edited", layerList)
         
      # plugIn, layer, feature, refresh, check_validity
      if qad_layer.updateFeatureToLayer(self.plugIn, self.poligonEntity.layer, f, False, False) == False:
         self.plugIn.destroyEditCommand()
         return False

      if removeOriginals:
         for layerEntitySet in entitySet.layerEntitySetList:            
            if qad_layer.deleteFeaturesToLayer(self.plugIn, layerEntitySet.layer, layerEntitySet.featureIds, False) == False:
               self.plugIn.destroyEditCommand()
               return 

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

      return True

   
   #============================================================================
   # convexHullEntitySetToPolygon
   #============================================================================
   def convexHullEntitySetToPolygon(self, entitySet, removeOriginals = False):
      """
      modifica il poligono corrente in modo che includa tutti i punti delle geometrie di entitySet
      """
      layerList = []
      layerList.append(self.poligonEntity.layer)
      pointsForConvexHull = []
      
      for layerEntitySet in entitySet.layerEntitySetList:
         layer = layerEntitySet.layer
         coordTransform = QgsCoordinateTransform(layer.crs(), self.poligonEntity.layer.crs())
         
         for featureId in layerEntitySet.featureIds:
            f = layerEntitySet.getFeature(featureId)
            # trasformo la geometria nel crs del layer del poligono da modificare
            geom = f.geometry()
            geom.transform(coordTransform)

            # Riduco la geometria in point o polyline
            simplifiedGeoms = qad_utils.asPointOrPolyline(geom)
            for simplifiedGeom in simplifiedGeoms:
               if simplifiedGeom.wkbType() == QGis.WKBLineString:
                  pointsForConvexHull.extend(simplifiedGeom.asPolyline())
               else:
                  pointsForConvexHull.append(simplifiedGeom.asPoint())
               
            if removeOriginals and layer.id() != self.poligonEntity.layerId():
               layerList.append(layer)

      geom = QgsGeometry.fromMultiPoint(pointsForConvexHull)
      geom = geom.convexHull()
      if geom is None:
         self.showMsg(QadMsg.translate("QAD", "Invalid object."))
         return False
         
      f = self.poligonEntity.getFeature()
      f.setGeometry(geom)

      self.plugIn.beginEditCommand("Feature edited", layerList)
         
      # plugIn, layer, feature, refresh, check_validity
      if qad_layer.updateFeatureToLayer(self.plugIn, self.poligonEntity.layer, f, False, False) == False:
         self.plugIn.destroyEditCommand()
         return False

      if removeOriginals:
         for layerEntitySet in entitySet.layerEntitySetList:            
            if qad_layer.deleteFeaturesToLayer(self.plugIn, layerEntitySet.layer, layerEntitySet.featureIds, False) == False:
               self.plugIn.destroyEditCommand()
               return 

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

      return True


   #============================================================================
   # dividePolygon
   #============================================================================
   def splitPolygon(self, splitLine, createNewEntities):
      """
      divide il poligono corrente usando una polilinea con i vertci in <plineVertices> in modo da generare o meno nuove entità
      """
      layerList = []
      layerList.append(self.poligonEntity.layer)
      
      splitLineTransformed = self.mapToLayerCoordinates(self.poligonEntity.layer, splitLine)
      f = self.poligonEntity.getFeature()
      geom = f.geometry()
      result, newGeoms, topologyTestPts = geom.splitGeometry(splitLineTransformed, False)

      if result <> 0 or len(newGeoms) == 0:
         self.showMsg(QadMsg.translate("QAD", "Invalid object."))
         return False
         
      newfeatures =[]
      if createNewEntities:
         for newGeom in newGeoms:
            newfeature = QgsFeature(f)
            newfeature.setGeometry(newGeom)
            newfeatures.append(newfeature)
      else:
         for newGeom in newGeoms:
            # Riduco la geometria in point o polyline
            simplifiedGeoms = qad_utils.asPointOrPolyline(newGeom)
            for simplifiedGeom in simplifiedGeoms:
               points = simplifiedGeom.asPolyline() # vettore di punti                     
               res = geom.addPart(points)
      
      f.setGeometry(geom)
      
      self.plugIn.beginEditCommand("Feature edited", layerList)
         
      # plugIn, layer, feature, refresh, check_validity
      if qad_layer.updateFeatureToLayer(self.plugIn, self.poligonEntity.layer, f, False, False) == False:
         self.plugIn.destroyEditCommand()
         return False

      if len(newfeatures) > 0:
         # plugIn, layer, features, coordTransform, refresh, check_validity
         if qad_layer.addFeaturesToLayer(self.plugIn, self.poligonEntity.layer, newfeatures, None, False, False) == False:
            self.plugIn.destroyEditCommand()
            return

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

      return True



   #============================================================================
   # waitForEntsel
   #============================================================================
   def waitForEntsel(self, msgMapTool, msg):
      if self.entSelClass is not None:
         del self.entSelClass
      self.step = 1
      self.entSelClass = QadEntSelClass(self.plugIn)
      self.entSelClass.msg = QadMsg.translate("Command_MAPMPEDIT", "Select polygon: ")
      # scarto la selezione di punti e polilinee
      self.entSelClass.checkPointLayer = False
      self.entSelClass.checkLineLayer = False
      self.entSelClass.checkPolygonLayer = True
      self.entSelClass.checkDimLayers = False     
      self.entSelClass.onlyEditableLayers = True

      self.entSelClass.run(msgMapTool, msg)
      

   #============================================================================
   # WaitForMainMenu
   #============================================================================
   def WaitForMainMenu(self):
      self.poligonEntity.selectOnLayer(False)
      keyWords = QadMsg.translate("Command_MAPMPEDIT", "Add") + "/" + \
                 QadMsg.translate("Command_MAPMPEDIT", "Delete") + "/" + \
                 QadMsg.translate("Command_MAPMPEDIT", "Union") + "/" + \
                 QadMsg.translate("Command_MAPMPEDIT", "Substract") + "/" + \
                 QadMsg.translate("Command_MAPMPEDIT", "Intersect") + "/" + \
                 QadMsg.translate("Command_MAPMPEDIT", "split Objects") + "/" + \
                 QadMsg.translate("Command_MAPMPEDIT", "split Parts") + "/" + \
                 QadMsg.translate("Command_MAPMPEDIT", "iNclude objs")
      englishKeyWords = "Add" + "/" + "Delete" + "/" + "Union" + "/" + "Substract" + "/" + "Intersect" "/" + \
                        "split Objects" + "/" + "split Parts" + "/" + "iNclude objs"

      if self.nOperationsToUndo > 0: # se c'è qualcosa che si può annullare
         keyWords = keyWords + "/" +  QadMsg.translate("Command_MAPMPEDIT", "Undo")
         englishKeyWords = englishKeyWords + "/" + "Undo"
      
      keyWords = keyWords + "/" + QadMsg.translate("Command_MAPMPEDIT", "eXit")
      englishKeyWords = englishKeyWords + "/" + "eXit"
                 
      default = QadMsg.translate("Command_MAPMPEDIT", "eXit")

      prompt = QadMsg.translate("Command_MAPMPEDIT", "Enter an option [{0}] <{1}>: ").format(keyWords, default)
      
      self.step = 2
      self.getPointMapTool().setSelectionMode(QadGetPointSelectionModeEnum.NONE)
      self.getPointMapTool().setDrawMode(QadGetPointDrawModeEnum.NONE)
      
      keyWords += "_" + englishKeyWords
      # si appresta ad attendere enter o una parola chiave         
      # msg, inputType, default, keyWords, nessun controllo
      self.waitFor(prompt, \
                   QadInputTypeEnum.KEYWORDS, \
                   None, \
                   keyWords, QadInputModeEnum.NONE)
      return False
      

   #============================================================================
   # waitForBoundary
   #============================================================================
   def waitForBoundary(self, msgMapTool, msg):
      if self.entSelClass is not None:
         del self.entSelClass
      self.entSelClass = QadEntSelClass(self.plugIn)
      self.entSelClass.msg = QadMsg.translate("Command_MAPMPEDIT", "Select boundary: ")
      # scarto la selezione di punti e polilinee
      self.entSelClass.checkPointLayer = False
      self.entSelClass.checkLineLayer = False
      self.entSelClass.checkPolygonLayer = True
      self.entSelClass.checkDimLayers = False
      self.entSelClass.onlyEditableLayers = True

      self.entSelClass.run(msgMapTool, msg)


   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
      
      if self.step == 0:
         self.waitForEntsel(msgMapTool, msg) # seleziona il poligono da modificare
         return False # continua
      
      #=========================================================================
      # RISPOSTA ALLA SELEZIONE POLIGONO DA MODIFICARE
      elif self.step == 1:
         if self.entSelClass.run(msgMapTool, msg) == True:
            if self.entSelClass.entity.isInitialized():
               self.poligonEntity.set(self.entSelClass.entity.layer, self.entSelClass.entity.featureId)
               layer = self.entSelClass.entity.layer
               self.poligonEntity.deselectOnLayer()
               self.WaitForMainMenu()
            else:
               if self.entSelClass.canceledByUsr == True: # fine comando
                  return True
               self.showMsg(QadMsg.translate("QAD", "No geometries in this position."))
               self.waitForEntsel(msgMapTool, msg)

         return False # continua

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL MENU PRINCIPALE
      elif self.step == 2: # dopo aver atteso una opzione 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

            self.WaitForMainMenu()
            return False 
         else: # l'opzione arriva come parametro della funzione
            value = msg

         self.poligonEntity.deselectOnLayer()

         if value == QadMsg.translate("Command_MAPMPEDIT", "Add") or value == "Add":
            self.SSGetClass.checkPointLayer = False # scarto i punto
            self.SSGetClass.run(msgMapTool, msg)
            self.step = 3
            return False
         elif value == QadMsg.translate("Command_MAPMPEDIT", "Delete") or value == "Delete":
            self.waitForBoundary(msgMapTool, msg)
            self.step = 4
            return False
         elif value == QadMsg.translate("Command_MAPMPEDIT", "Union") or value == "Union":
            self.SSGetClass.checkPointLayer = False # scarto i layer puntuali
            self.SSGetClass.run(msgMapTool, msg)
            self.step = 5
            return False
         elif value == QadMsg.translate("Command_MAPMPEDIT", "Substract") or value == "Substract":
            self.SSGetClass.checkPointLayer = False # scarto i layer puntuali
            self.SSGetClass.run(msgMapTool, msg)
            self.step = 6
            return False
         elif value == QadMsg.translate("Command_MAPMPEDIT", "Intersect") or value == "Intersect":
            self.SSGetClass.checkPointLayer = False # scarto i layer puntuali
            self.SSGetClass.run(msgMapTool, msg)
            self.step = 7
            return False
         elif value == QadMsg.translate("Command_MAPMPEDIT", "split Objects") or value == "split Objects":
            # Disegna una polilinea di divisione del poligono
            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 = 9
            return False
         elif value == QadMsg.translate("Command_MAPMPEDIT", "split Parts") or value == "split Parts":
            # Disegna una polilinea di divisione del poligono
            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 = 10
            return False
         elif value == QadMsg.translate("Command_MAPMPEDIT", "iNclude objs") or value == "iNclude objs":
            self.SSGetClass.checkPointLayer = True # includo i layer puntuali
            self.SSGetClass.run(msgMapTool, msg)
            self.step = 8
            return False
         elif value == QadMsg.translate("Command_MAPMPEDIT", "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."))
         elif value == QadMsg.translate("Command_MAPMPEDIT", "eXit") or value == "eXit":
            return True # fine comando
         else:
            return True # fine comando
         
         self.WaitForMainMenu()
         return False      

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DELLA MODALITA' DI ADD (da step = 2)
      elif self.step == 3:
         if self.SSGetClass.run(msgMapTool, msg) == True:
            if self.SSGetClass.entitySet.count() > 0:
               self.addEntitySetToPolygon(self.SSGetClass.entitySet)
            self.reinitSSGetClass()
            self.WaitForMainMenu()
         return False
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DELLA MODALITA' DI DELETE (da step = 2)
      elif self.step == 4:
         if self.entSelClass.run(msgMapTool, msg) == True:
            if self.setCurrentSubGeom(self.entSelClass) == True:
               self.delCurrentSubGeomToPolygon()
               self.WaitForMainMenu()
               return False
            else:
               if self.entSelClass.canceledByUsr == True: # fine selezione entità
                  self.WaitForMainMenu()
               else:
                  self.waitForBoundary(msgMapTool, msg)
         return False # continua

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DELLA MODALITA' DI UNION (da step = 2)
      elif self.step == 5: # dopo aver atteso una entità si riavvia il comando
         if self.SSGetClass.run(msgMapTool, msg) == True:
            if self.SSGetClass.entitySet.count() > 0:
               self.unionIntersSubtractEntitySetToPolygon(self.SSGetClass.entitySet, QadMAPMPEDITCommandOpTypeEnum.UNION)
            self.reinitSSGetClass()
            self.WaitForMainMenu()
         return False # continua

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DELLA MODALITA' DI SUBTRACT (da step = 2)
      elif self.step == 6: # dopo aver atteso una entità si riavvia il comando
         if self.SSGetClass.run(msgMapTool, msg) == True:
            if self.SSGetClass.entitySet.count() > 0:
               self.unionIntersSubtractEntitySetToPolygon(self.SSGetClass.entitySet, QadMAPMPEDITCommandOpTypeEnum.DIFFERENCE)
            self.reinitSSGetClass()
            self.WaitForMainMenu()
         return False # continua

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DELLA MODALITA' DI INTERSECT (da step = 2)
      elif self.step == 7: # dopo aver atteso una entità si riavvia il comando
         if self.SSGetClass.run(msgMapTool, msg) == True:
            if self.SSGetClass.entitySet.count() > 0:
               self.unionIntersSubtractEntitySetToPolygon(self.SSGetClass.entitySet, QadMAPMPEDITCommandOpTypeEnum.INTERSECTION)
            self.reinitSSGetClass()
            self.WaitForMainMenu()
         return False # continua

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DELLA MODALITA' DI INCLUDE OBJS (da step = 2)
      elif self.step == 8: # dopo aver atteso una entità si riavvia il comando
         if self.SSGetClass.run(msgMapTool, msg) == True:
            if self.SSGetClass.entitySet.count() > 0:
               self.convexHullEntitySetToPolygon(self.SSGetClass.entitySet)
            self.reinitSSGetClass()
            self.WaitForMainMenu()
         return False # continua

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DELLA LINEA DI DIVISIONE (da step = 2)
      elif self.step == 9: # dopo aver atteso un punto si riavvia il comando
         if self.PLINECommand.run(msgMapTool, msg) == True:
            self.showMsg("\n")
            self.splitPolygon(self.PLINECommand.vertices, True)
            del self.PLINECommand
            self.PLINECommand = None
            self.WaitForMainMenu()
         return False

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DELLA LINEA DI DIVISIONE (da step = 2)
      elif self.step == 10: # dopo aver atteso un punto si riavvia il comando
         if self.PLINECommand.run(msgMapTool, msg) == True:
            self.showMsg("\n")
            self.splitPolygon(self.PLINECommand.vertices, False)
            del self.PLINECommand
            self.PLINECommand = None
            self.WaitForMainMenu()
         return False class QadJOINCommandClass(QadCommandClass):

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

   def getName(self):
      return QadMsg.translate("Command_list", "JOIN")
   
   def getEnglishName(self):
      return "JOIN"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runJOINCommand)

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/join.png")
   
   def getNote(self):
      # impostare le note esplicative del comando      
      return QadMsg.translate("Command_JOIN", "Join existing geometries.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      
      self.entity = QadEntity()
      
      self.SSGetClass = None
      self.entSelClass = None
   
   def __del__(self):
      QadCommandClass.__del__(self)
      if self.SSGetClass is not None:  del self.SSGetClass


   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      if self.step == 1: # quando si é in fase di selezione entità
         return self.entSelClass.getPointMapTool(drawMode)
      elif self.step == 2: # quando si é in fase di selezione gruppo entità
         return self.SSGetClass.getPointMapTool()
      else:
         return QadCommandClass.getPointMapTool(self, drawMode)


   def getCurrentContextualMenu(self):
      if self.step == 1: # quando si é in fase di selezione entità
         return self.entSelClass.getCurrentContextualMenu()
      elif self.step == 2: # quando si é in fase di selezione gruppo entità
         return self.SSGetClass.getCurrentContextualMenu()()
      else:
         return self.contextualMenu


   def reinitSSGetClass(self):
      if self.SSGetClass is not None: del self.SSGetClass
      
      self.SSGetClass = QadSSGetClass(self.plugIn)
      self.SSGetClass.onlyEditableLayers = True
      self.SSGetClass.checkDimLayers = False # scarto le quote
      geometryType = self.entity.layer.geometryType()
      if geometryType == QGis.Point:
         self.SSGetClass.checkPointLayer = True
         self.SSGetClass.checkLineLayer = False
         self.SSGetClass.checkPolygonLayer = False
      elif geometryType == QGis.Line:
         self.SSGetClass.checkPointLayer = False
         self.SSGetClass.checkLineLayer = True
         self.SSGetClass.checkPolygonLayer = True
      elif geometryType == QGis.Polygon:
         self.SSGetClass.checkPointLayer = False
         self.SSGetClass.checkLineLayer = True
         self.SSGetClass.checkPolygonLayer = True
   

   #============================================================================
   # addEntitySetToPoint
   #============================================================================
   def addEntitySetToPoint(self, entitySet, removeOriginals = True):
      """
      Aggiunge il set di entità al punto da modificare
      """
      geom = self.entity.getGeometry()
      layerList = []
      layerList.append(self.entity.layer)
      
      for layerEntitySet in entitySet.layerEntitySetList:
         layer = layerEntitySet.layer
         if layer.geometryType() != QGis.Point:
            self.showMsg(QadMsg.translate("QAD", "Invalid object."))
            return False

         if removeOriginals: layerList.append(layer)
         coordTransform = QgsCoordinateTransform(layer.crs(), self.entity.layer.crs())

         for featureId in layerEntitySet.featureIds:
            # se la feature è quella di entity è errore 
            if layer.id() == self.entity.layerId() and featureId == self.entity.featureId:
               self.showMsg(QadMsg.translate("QAD", "Invalid object."))
               return False
            
            f = layerEntitySet.getFeature(featureId)
            # trasformo la geometria nel crs del layer dell'entità da modificare
            geomToAdd = f.geometry()
            geomToAdd.transform(coordTransform)
            
            simplifiedGeoms = qad_utils.asPointOrPolyline(geomToAdd)
            for simplifiedGeom in simplifiedGeoms:
               point = simplifiedGeom.asPoint()
               # aggiungo una parte
               if geom.addPart([point]) != 0: # 0 in case of success
                  self.showMsg(QadMsg.translate("QAD", "Invalid object."))
                  return False

      f = self.entity.getFeature()
      f.setGeometry(geom)

      layerList = entitySet.getLayerList()
      layerList.append(self.entity.layer)

      self.plugIn.beginEditCommand("Feature edited", layerList)
         
      # plugIn, layer, feature, refresh, check_validity
      if qad_layer.updateFeatureToLayer(self.plugIn, self.entity.layer, f, False, False) == False:
         self.plugIn.destroyEditCommand()
         return False

      if removeOriginals:
         for layerEntitySet in entitySet.layerEntitySetList:            
            if qad_layer.deleteFeaturesToLayer(self.plugIn, layerEntitySet.layer, layerEntitySet.featureIds, False) == False:
               self.plugIn.destroyEditCommand()
               return 

      self.plugIn.endEditCommand()

      return True
   

   #============================================================================
   # addEntitySetToPolyline
   #============================================================================
   def addEntitySetToPolyline(self, entitySet, removeOriginals = True):
      """
      Aggiunge il set di entità alla polilinea da modificare
      """
      geom = self.entity.getGeometry()
      layerList = []
      layerList.append(self.entity.layer)
      
      for layerEntitySet in entitySet.layerEntitySetList:
         layer = layerEntitySet.layer
         if layer.geometryType() != QGis.Polygon and layer.geometryType() != QGis.Line:
            self.showMsg(QadMsg.translate("QAD", "Invalid object."))
            return False

         if removeOriginals: layerList.append(layer)
         coordTransform = QgsCoordinateTransform(layer.crs(), self.entity.layer.crs())

         for featureId in layerEntitySet.featureIds:
            # se la feature è quella di entity è errore 
            if layer.id() == self.entity.layerId() and featureId == self.entity.featureId:
               self.showMsg(QadMsg.translate("QAD", "Invalid object."))
               return False
            
            f = layerEntitySet.getFeature(featureId)
            # trasformo la geometria nel crs del layer dell'entità da modificare
            geomToAdd = f.geometry()
            geomToAdd.transform(coordTransform)
            
            # Riduco la geometria in point o polyline
            simplifiedGeoms = qad_utils.asPointOrPolyline(geomToAdd)
            for simplifiedGeom in simplifiedGeoms:
               points = simplifiedGeom.asPolyline() # vettore di punti                     
               # aggiungo una parte
               if geom.addPart(points) != 0: # 0 in case of success
                  self.showMsg(QadMsg.translate("QAD", "Invalid object."))
                  return False

      f = self.entity.getFeature()
      f.setGeometry(geom)

      layerList = entitySet.getLayerList()
      layerList.append(self.entity.layer)

      self.plugIn.beginEditCommand("Feature edited", layerList)
         
      # plugIn, layer, feature, refresh, check_validity
      if qad_layer.updateFeatureToLayer(self.plugIn, self.entity.layer, f, False, False) == False:
         self.plugIn.destroyEditCommand()
         return False

      if removeOriginals:
         for layerEntitySet in entitySet.layerEntitySetList:            
            if qad_layer.deleteFeaturesToLayer(self.plugIn, layerEntitySet.layer, layerEntitySet.featureIds, False) == False:
               self.plugIn.destroyEditCommand()
               return 

      self.plugIn.endEditCommand()

      return True
   

   #============================================================================
   # addEntitySetToPolygon
   #============================================================================
   def addEntitySetToPolygon(self, entitySet, removeOriginals = True):
      """
      Aggiunge il set di entità al poligono da modificare
      """
      geom = self.entity.getGeometry()
      layerList = []
      layerList.append(self.entity.layer)
      
      for layerEntitySet in entitySet.layerEntitySetList:
         layer = layerEntitySet.layer
         if layer.geometryType() != QGis.Polygon and layer.geometryType() != QGis.Line:
            self.showMsg(QadMsg.translate("QAD", "Invalid object."))
            return False

         if removeOriginals: layerList.append(layer)
         coordTransform = QgsCoordinateTransform(layer.crs(), self.entity.layer.crs())

         for featureId in layerEntitySet.featureIds:
            # se la feature è quella di entity è errore 
            if layer.id() == self.entity.layerId() and featureId == self.entity.featureId:
               self.showMsg(QadMsg.translate("QAD", "Invalid object."))
               return False
            
            f = layerEntitySet.getFeature(featureId)
            # trasformo la geometria nel crs del layer del poligono da modificare
            geomToAdd = f.geometry()
            geomToAdd.transform(coordTransform)
            
            # se il poligono è contenuto nella geometria da aggiungere
            if geomToAdd.contains(geom):
               # Riduco la geometria in point o polyline
               simplifiedGeoms = qad_utils.asPointOrPolyline(geom)
               # deve essere un poligono senza ring
               if len(simplifiedGeoms) != 1 or simplifiedGeoms[0].wkbType() != QGis.WKBLineString:
                  self.showMsg(QadMsg.translate("QAD", "Invalid object."))
                  return False
               points = simplifiedGeoms[0].asPolyline() # vettore di punti
               # aggiungo un'isola
               if geomToAdd.addRing(points) != 0: # 0 in case of success
                  self.showMsg(QadMsg.translate("QAD", "Invalid object."))
                  return False
               del geom
               geom = QgsGeometry.fromPolygon(geomToAdd.asPolygon())
            else: # se il poligono non è contenuto nella geometria da aggiungere
               # Riduco la geometria in point o polyline
               simplifiedGeoms = qad_utils.asPointOrPolyline(geomToAdd)
               for simplifiedGeom in simplifiedGeoms:
                  points = simplifiedGeom.asPolyline() # vettore di punti                     
                  # se la geometria da aggiungere è contenuta nel poligono
                  if geom.contains(QgsGeometry.fromPolyline(points)):
                     # aggiungo un'isola
                     if geom.addRing(points) != 0: # 0 in case of success
                        self.showMsg(QadMsg.translate("QAD", "Invalid object."))
                        return False
                  else:
                     # aggiungo una parte
                     if geom.addPart(points) != 0: # 0 in case of success
                        self.showMsg(QadMsg.translate("QAD", "Invalid object."))
                        return False

      f = self.entity.getFeature()
      f.setGeometry(geom)

      layerList = entitySet.getLayerList()
      layerList.append(self.entity.layer)

      self.plugIn.beginEditCommand("Feature edited", layerList)
         
      # plugIn, layer, feature, refresh, check_validity
      if qad_layer.updateFeatureToLayer(self.plugIn, self.entity.layer, f, False, False) == False:
         self.plugIn.destroyEditCommand()
         return False

      if removeOriginals:
         for layerEntitySet in entitySet.layerEntitySetList:            
            if qad_layer.deleteFeaturesToLayer(self.plugIn, layerEntitySet.layer, layerEntitySet.featureIds, False) == False:
               self.plugIn.destroyEditCommand()
               return 

      self.plugIn.endEditCommand()

      return True


   #============================================================================
   # waitForEntsel
   #============================================================================
   def waitForEntsel(self, msgMapTool, msg):
      if self.entSelClass is not None:
         del self.entSelClass
      self.step = 1
      self.entSelClass = QadEntSelClass(self.plugIn)
      self.entSelClass.msg = QadMsg.translate("Command_JOIN", "Select object to join to: ")
      # scarto la selezione di quote
      self.entSelClass.checkDimLayers = False     
      self.entSelClass.onlyEditableLayers = True
      self.entSelClass.deselectOnFinish = True
      
      self.entSelClass.run(msgMapTool, msg)


   #============================================================================
   # waitForSSsel
   #============================================================================
   def waitForSSsel(self, msgMapTool, msg):
      self.reinitSSGetClass()
      self.step = 2
      self.showMsg(QadMsg.translate("Command_JOIN", "\nSelect objects to join: "))
      self.SSGetClass.run(msgMapTool, msg)


   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
      
      if self.step == 0:
         self.waitForEntsel(msgMapTool, msg) # seleziona l'oggetto a cui aggregarsi
         return False # continua
      
      #=========================================================================
      # RISPOSTA ALLA SELEZIONE ENTITA' DA MODIFICARE
      elif self.step == 1:
         if self.entSelClass.run(msgMapTool, msg) == True:
            if self.entSelClass.entity.isInitialized():
               self.entity.set(self.entSelClass.entity)

               self.waitForSSsel(msgMapTool, msg)
            else:
               if self.entSelClass.canceledByUsr == True: # fine comando
                  return True
               self.showMsg(QadMsg.translate("QAD", "No geometries in this position."))
               self.waitForEntsel(msgMapTool, msg)

         return False # continua

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL GRUPPO DI SELEZIONE (da step = 1)
      elif self.step == 2:
         if self.SSGetClass.run(msgMapTool, msg) == True:
            if self.SSGetClass.entitySet.count() > 0:
               geometryType = self.entity.layer.geometryType()
               if geometryType == QGis.Point:
                  self.addEntitySetToPoint(self.SSGetClass.entitySet)
               elif geometryType == QGis.Line:
                  self.addEntitySetToPolyline(self.SSGetClass.entitySet)
               elif geometryType == QGis.Polygon:
                  self.addEntitySetToPolygon(self.SSGetClass.entitySet)
               
               return True
               
            self.waitForSSsel(msgMapTool, msg)
         return False class QadDISJOINCommandClass(QadCommandClass):

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

   def getName(self):
      return QadMsg.translate("Command_list", "DISJOIN")
   
   def getEnglishName(self):
      return "DISJOIN"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runDISJOINCommand)

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/disjoin.png")
   
   def getNote(self):
      # impostare le note esplicative del comando      
      return QadMsg.translate("Command_DISJOIN", "Disjoin existing geometries.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      
      self.entity = QadEntity()
      
      self.SSGetClass = QadSSGetClass(plugIn)
      self.SSGetClass.onlyEditableLayers = False
      self.SSGetClass.checkDimLayers = False # scarto le quote
      
      self.entSelClass = None
      
      self.currSubGeom = None
      self.currAtSubGeom = None
      
   
   def __del__(self):
      QadCommandClass.__del__(self)
      del self.SSGetClass


   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      if self.step == 1: # quando si é in fase di selezione entità
         return self.entSelClass.getPointMapTool(drawMode)
      else:
         return QadCommandClass.getPointMapTool(self, drawMode)


   def getCurrentContextualMenu(self):
      if self.step == 1: # quando si é in fase di selezione entità
         return self.entSelClass.getCurrentContextualMenu()
      else:
         return self.contextualMenu


   #============================================================================
   # setCurrentSubGeom
   #============================================================================
   def setCurrentSubGeom(self, entSelClass):
      """
      Setta la sottogeometria corrente
      """
      self.currSubGeom = None
      self.currAtSubGeom = None

      # verifico che sia stata selezionata un'entità
      if entSelClass.entity.isInitialized() == False:
         self.showMsg(QadMsg.translate("QAD", "No geometries in this position."))
         return False
      # verifico che sia stata selezionata attraverso un punto
      # (per capire quale sottogeometria è stata selezionata)
      if entSelClass.point is None: return False

      self.entity.set(entSelClass.entity)
      
      geom = self.layerToMapCoordinates(entSelClass.entity.layer, entSelClass.entity.getGeometry())
      
      # ritorna una tupla (<The squared cartesian distance>,
      #                    <minDistPoint>
      #                    <afterVertex>
      #                    <leftOf>)
      dummy = qad_utils.closestSegmentWithContext(entSelClass.point, geom)
      if dummy[2] is None:
         return False
      # ritorna la sotto-geometria al vertice <atVertex> e la sua posizione nella geometria (0-based)
      self.currSubGeom, self.currAtSubGeom = qad_utils.getSubGeomAtVertex(geom, dummy[2])
      if self.currSubGeom is None or self.currAtSubGeom is None:
         self.currSubGeom = None
         self.currAtSubGeom = None
         return False
      
      return True


   #============================================================================
   # disjoinCurrentSubGeomToPolygon
   #============================================================================
   def disjoinCurrentSubGeomToPolygon(self):
      """
      Sconnette la sotto-geometria corrente del poligono da modificare creando una nuova entità
      """
      layer = self.entity.layer
      # la posizione é espressa con una lista (<index ogg. princ> [<index ogg. sec.>])
      part = self.currAtSubGeom[0]
      ring = self.currAtSubGeom[1] if len(self.currAtSubGeom) == 2 else None
      
      geom = self.entity.getGeometry()
      wkbType = geom.wkbType()
      if wkbType == QGis.WKBMultiPoint or wkbType == QGis.WKBMultiLineString:
         if geom.deletePart(part) == False: # disgrego una parte
            self.showMsg(QadMsg.translate("QAD", "Invalid object."))
            return False
         newGeom = self.mapToLayerCoordinates(layer, self.currSubGeom)
      elif wkbType == QGis.WKBPolygon or wkbType == QGis.WKBMultiPolygon:
         if ring is not None: # disgrego un'isola 
            if geom.deleteRing(ring + 1, part) == False: # cancello una isola (Ring 0 is outer ring and can't be deleted)
               self.showMsg(QadMsg.translate("QAD", "Invalid object."))
               return False
            newGeom = QgsGeometry.fromPolygon([self.mapToLayerCoordinates(layer, self.currSubGeom).asPolyline()])
         else: # disgrego una parte
            if wkbType == QGis.WKBPolygon:
               self.showMsg(QadMsg.translate("QAD", "Invalid object."))
               return False
            
            newGeom = QgsGeometry.fromPolygon([self.mapToLayerCoordinates(layer, self.currSubGeom).asPolyline()])
            ring = 0
            ringGeom = qad_utils.getSubGeomAt(geom, [part, ring])
            # se la parte ha delle isole
            while ringGeom is not None:
               # aggiungo un'isola
               points = ringGeom.asPolyline() # vettore di punti
               if newGeom.addRing(points) != 0: # 0 in case of success
                  self.showMsg(QadMsg.translate("QAD", "Invalid object."))
                  return False
               ring = ring + 1
               ringGeom = qad_utils.getSubGeomAt(geom, [part, ring])

            if geom.deletePart(part) == False: # cancello una parte
               self.showMsg(QadMsg.translate("QAD", "Invalid object."))
               return False
      else:
         self.showMsg(QadMsg.translate("QAD", "Invalid object."))
         return False

      f = self.entity.getFeature()
      f.setGeometry(geom)

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

      # Aggiungo nuova feature
      newF = QgsFeature(f)
      newF.setGeometry(newGeom)
      if qad_layer.addFeatureToLayer(self.plugIn, self.entity.layer, newF, None, False, False) == False:
         self.plugIn.destroyEditCommand()
         return False
         
      self.plugIn.endEditCommand()

      return True


   #============================================================================
   # waitForEntsel
   #============================================================================
   def waitForEntsel(self, msgMapTool, msg):
      if self.entSelClass is not None:
         del self.entSelClass
      self.step = 1
      self.entSelClass = QadEntSelClass(self.plugIn)
      self.entSelClass.msg = QadMsg.translate("Command_DISJOIN", "Select object to disjoin: ")
      # scarto la selezione di quote
      self.entSelClass.checkDimLayers = False     
      self.entSelClass.onlyEditableLayers = True
      self.entSelClass.deselectOnFinish = True
      
      self.entSelClass.run(msgMapTool, msg)


   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
      
      if self.step == 0:
         self.waitForEntsel(msgMapTool, msg) # seleziona l'oggetto da disgregare
         return False # continua
      
      #=========================================================================
      # RISPOSTA ALLA SELEZIONE ENTITA' DA MODIFICARE
      elif self.step == 1:
         if self.entSelClass.run(msgMapTool, msg) == True:
            if self.setCurrentSubGeom(self.entSelClass) == True:
               if self.disjoinCurrentSubGeomToPolygon() == True:
                  return True
            else:
               if self.entSelClass.canceledByUsr == True: # fine comando
                  return True
               self.showMsg(QadMsg.translate("QAD", "No geometries in this position."))
               
            self.waitForEntsel(msgMapTool, msg)
            
         return False # continua class QadARRAYCommandClass(QadCommandClass):

   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadARRAYCommandClass(self.plugIn)
   
   def getName(self):
      return QadMsg.translate("Command_list", "ARRAY")

   def getEnglishName(self):
      return "ARRAY"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runARRAYCommand)

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/arrayRect.png")

   def getNote(self):
      # impostare le note esplicative del comando
      return QadMsg.translate("Command_ARRAY", "Creates copies of objects in a regularly spaced rectangular, polar, or path array.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      self.SSGetClass = QadSSGetClass(plugIn)
      self.SSGetClass.onlyEditableLayers = True
      self.entSelClass = None
      self.entitySet = QadEntitySet()
      self.defaultValue = None
      
      self.basePt = QgsPoint()      
      self.arrayType = self.plugIn.lastArrayType_array
      self.distanceBetweenRows = None
      self.distanceBetweenCols = None
      self.itemsRotation = self.plugIn.lastItemsRotation_array
      self.delObj = QadVariables.get(QadMsg.translate("Environment variables", "DELOBJ"))
      self.delOrigSelSet = False
      if self.delObj == QadDELOBJEnum.DELETE_ALL: # Delete all defining geometry
         self.delOrigSelSet = True

      # serie rettangolare
      self.rectangleAngle = self.plugIn.lastRectangleAngle_array
      self.rectangleCols = self.plugIn.lastRectangleCols_array
      self.rectangleRows = self.plugIn.lastRectangleRows_array
      self.firstPt = QgsPoint() # primo punto per misurare la distanza tra righe
      
      # serie traiettoria
      self.pathTangentDirection = self.plugIn.lastPathTangentDirection_array
      self.pathRows = self.plugIn.lastPathRows_array
      self.pathItemsNumber = 1
      self.pathLinearObjectList = qad_utils.QadLinearObjectList()
      self.pathMethod = QadARRAYCommandClassPathMethodTypeEnum.MEASURE
      self.distanceFromStartPt = 0.0 # uso interno quando si imposta il metodo dividi
      
      # serie polare
      self.centerPt = QgsPoint()
      self.polarItemsNumber = self.plugIn.lastPolarItemsNumber_array
      self.polarAngleBetween = self.plugIn.lastPolarAngleBetween_array
      self.polarRows = self.plugIn.lastPolarRows_array
      
      self.GetDistClass = None
      self.GetAngleClass = None
      
      self.featureCache = [] # lista di (layer, feature)

   def __del__(self):
      QadCommandClass.__del__(self)
      if self.SSGetClass is not None:
         del self.SSGetClass
      
   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      if self.step == QadARRAYCommandClassStepEnum.ASK_FOR_SELSET: # quando si é in fase di selezione entità
         return self.SSGetClass.getPointMapTool()
      # quando si é in fase di richiesta rotazione
      elif self.step == QadARRAYCommandClassStepEnum.ASK_FOR_ANGLE or \
           self.step == QadARRAYCommandClassStepEnum.ASK_FOR_TAN_DIRECTION or \
           self.step == QadARRAYCommandClassStepEnum.ASK_FOR_ANGLE_BETWEEN_ITEMS or \
           self.step == QadARRAYCommandClassStepEnum.ASK_FOR_FULL_ANGLE:
         return self.GetAngleClass.getPointMapTool()
      # quando si é in fase di richiesta distanza
      elif self.step == QadARRAYCommandClassStepEnum.ASK_FOR_COLUMN_SPACE_2PT or \
           self.step == QadARRAYCommandClassStepEnum.ASK_FOR_ROW_SPACE_TOT or \
           self.step == QadARRAYCommandClassStepEnum.ASK_FOR_COLUMN_SPACE_TOT or \
           self.step == QadARRAYCommandClassStepEnum.ASK_FOR_ITEM_SPACE or \
           self.step == QadARRAYCommandClassStepEnum.ASK_FOR_ROW_SPACE_2PT:
         return self.GetDistClass.getPointMapTool()
      else:
         if (self.plugIn is not None):
            if self.PointMapTool is None:
               self.PointMapTool = Qad_array_maptool(self.plugIn)
            return self.PointMapTool
         else:
            return None


   def getCurrentContextualMenu(self):
      if self.step == QadARRAYCommandClassStepEnum.ASK_FOR_SELSET: # quando si é in fase di selezione entità
         return self.SSGetClass.getCurrentContextualMenu()
      # quando si é in fase di richiesta rotazione
      elif self.step == QadARRAYCommandClassStepEnum.ASK_FOR_ANGLE or \
           self.step == QadARRAYCommandClassStepEnum.ASK_FOR_TAN_DIRECTION or \
           self.step == QadARRAYCommandClassStepEnum.ASK_FOR_ANGLE_BETWEEN_ITEMS or \
           self.step == QadARRAYCommandClassStepEnum.ASK_FOR_FULL_ANGLE:
         return self.GetAngleClass.getCurrentContextualMenu()
      # quando si é in fase di richiesta distanza
      elif self.step == QadARRAYCommandClassStepEnum.ASK_FOR_COLUMN_SPACE_2PT or \
           self.step == QadARRAYCommandClassStepEnum.ASK_FOR_ROW_SPACE_TOT or \
           self.step == QadARRAYCommandClassStepEnum.ASK_FOR_COLUMN_SPACE_TOT or \
           self.step == QadARRAYCommandClassStepEnum.ASK_FOR_ITEM_SPACE or \
           self.step == QadARRAYCommandClassStepEnum.ASK_FOR_ROW_SPACE_2PT:
         return self.GetDistClass.getCurrentContextualMenu()
      else:
         return self.contextualMenu


   #============================================================================
   # updatePointMapToolParams
   #============================================================================
   def updatePointMapToolParams(self):
      self.step = -1 * self.step # trucchetto per prendere il map tool base
      self.getPointMapTool().refreshSnapType() # aggiorno lo snapType che può essere variato da altri maptool
      
      self.getPointMapTool().entitySet = self.entitySet
      self.getPointMapTool().basePt = self.basePt
      self.getPointMapTool().arrayType = self.arrayType
      self.getPointMapTool().distanceBetweenRows = self.distanceBetweenRows
      self.getPointMapTool().distanceBetweenCols = self.distanceBetweenCols
      self.getPointMapTool().itemsRotation = self.itemsRotation

      if self.arrayType == QadARRAYCommandClassSeriesTypeEnum.RECTANGLE: # serie rettangolare
         self.getPointMapTool().rectangleAngle = self.rectangleAngle
         self.getPointMapTool().rectangleCols = self.rectangleCols
         self.getPointMapTool().rectangleRows = self.rectangleRows
         self.getPointMapTool().firstPt = self.firstPt
         self.getPointMapTool().doRectangleArray()
      elif self.arrayType == QadARRAYCommandClassSeriesTypeEnum.PATH: # serie traiettoria
         self.getPointMapTool().pathTangentDirection = self.pathTangentDirection
         self.getPointMapTool().pathRows = self.pathRows
         self.getPointMapTool().pathItemsNumber = self.pathItemsNumber
         self.getPointMapTool().pathLinearObjectList = self.pathLinearObjectList
         self.getPointMapTool().distanceFromStartPt = self.distanceFromStartPt
         self.getPointMapTool().doPathArray()
      elif self.arrayType == QadARRAYCommandClassSeriesTypeEnum.POLAR: # serie polare
         self.getPointMapTool().centerPt = self.centerPt
         self.getPointMapTool().polarItemsNumber = self.polarItemsNumber
         self.getPointMapTool().polarAngleBetween = self.polarAngleBetween
         self.getPointMapTool().polarRows = self.polarRows
         self.getPointMapTool().doPolarArray()

      self.step = -1 * self.step # trucchetto per prendere il map tool base


   #============================================================================
   # setEntitySet
   #============================================================================
   def setEntitySet(self, ss):
      self.entitySet.set(ss)
      rect = self.entitySet.boundingBox(self.plugIn.canvas.mapSettings().destinationCrs())
      self.distanceBetweenRows = rect.height() + (rect.height() / 2) if rect.height() != 0 else 1
      self.distanceBetweenCols = rect.width() + (rect.width() / 2) if rect.width() != 0 else 1
      center = rect.center()
      self.basePt.setX(center.x())
      self.basePt.setY(center.y())


   #============================================================================
   # doRectangleArray
   #============================================================================
   def doRectangleArray(self):
      entity = QadEntity()
      # copio entitySet
      entitySet = QadEntitySet(self.entitySet)
      
      self.plugIn.beginEditCommand("Feature copied", entitySet.getLayerList())

      for layerEntitySet in entitySet.layerEntitySetList:
         layer = layerEntitySet.layer
         
         while len(layerEntitySet.featureIds) > 0:
            featureId = layerEntitySet.featureIds[0]
            
            f = layerEntitySet.getFeature(featureId)
            if f is None:
               del layerEntitySet.featureIds[0]
               continue

            # verifico se l'entità appartiene ad uno stile di quotatura
            dimEntity = QadDimStyles.getDimEntity(layer, f.id())
            if dimEntity is None:
               entity.set(layer, f.id())
               if qad_array_fun.arrayRectangleEntity(self.plugIn, entity, self.basePt, self.rectangleRows, self.rectangleCols, \
                                                     self.distanceBetweenRows, self.distanceBetweenCols, self.rectangleAngle, self.itemsRotation,
                                                     True, None) == False:
                  self.plugIn.destroyEditCommand()
                  return
               del layerEntitySet.featureIds[0] # la rimuovo da entitySet
            else:
               if qad_array_fun.arrayRectangleEntity(self.plugIn, dimEntity, self.basePt, self.rectangleRows, self.rectangleCols, \
                                                     self.distanceBetweenRows, self.distanceBetweenCols, self.rectangleAngle, self.itemsRotation,
                                                     True, None) == False:
                  self.plugIn.destroyEditCommand()
                  return
               dimEntitySet = dimEntity.getEntitySet()
               entitySet.subtract(dimEntitySet) # la rimuovo da entitySet

      if self.delOrigSelSet: # se devo rimuovere gli oggetti originali
         for layerEntitySet in self.entitySet.layerEntitySetList:
            # plugIn, layer, featureIds, refresh
            if qad_layer.deleteFeaturesToLayer(self.plugIn, layerEntitySet.layer, \
                                               layerEntitySet.featureIds, False) == False:
               self.plugIn.destroyEditCommand()
               return
         
      self.plugIn.endEditCommand()


   #============================================================================
   # doPathArray
   #============================================================================
   def doPathArray(self):
      entity = QadEntity()
      # copio entitySet
      entitySet = QadEntitySet(self.entitySet)
      
      self.plugIn.beginEditCommand("Feature copied", entitySet.getLayerList())

      for layerEntitySet in entitySet.layerEntitySetList:
         layer = layerEntitySet.layer
         
         while len(layerEntitySet.featureIds) > 0:
            featureId = layerEntitySet.featureIds[0]
            # verifico se l'entità appartiene ad uno stile di quotatura
            dimEntity = QadDimStyles.getDimEntity(layer, featureId)
            
            f = layerEntitySet.getFeature(featureId)
            if f is None:
               del layerEntitySet.featureIds[0]
               continue

            # verifico se l'entità appartiene ad uno stile di quotatura
            dimEntity = QadDimStyles.getDimEntity(layer, f.id())
            if dimEntity is None:
               entity.set(layer, f.id())
               if qad_array_fun.arrayPathEntity(self.plugIn, entity, self.basePt, self.pathRows, self.pathItemsNumber, \
                                                self.distanceBetweenRows, self.distanceBetweenCols, self.pathTangentDirection, self.itemsRotation, \
                                                self.pathLinearObjectList, self.distanceFromStartPt, True, None) == False:
                  self.plugIn.destroyEditCommand()
                  return
               del layerEntitySet.featureIds[0] # la rimuovo da entitySet
            else:
               if qad_array_fun.arrayPathEntity(self.plugIn, dimEntity, self.basePt, self.pathRows, self.pathItemsNumber, \
                                                self.distanceBetweenRows, self.distanceBetweenCols, self.pathTangentDirection, self.itemsRotation, \
                                                self.pathLinearObjectList, self.distanceFromStartPt, True, None) == False:
                  self.plugIn.destroyEditCommand()
                  return
               dimEntitySet = dimEntity.getEntitySet()
               entitySet.subtract(dimEntitySet) # la rimuovo da entitySet
               
      if self.delOrigSelSet: # se devo rimuovere gli oggetti originali
         for layerEntitySet in self.entitySet.layerEntitySetList:
            # plugIn, layer, featureIds, refresh
            if qad_layer.deleteFeaturesToLayer(self.plugIn, layerEntitySet.layer, \
                                               layerEntitySet.featureIds, False) == False:
               self.plugIn.destroyEditCommand()
               return

      self.plugIn.endEditCommand()


   #============================================================================
   # doPolarArray
   #============================================================================
   def doPolarArray(self):
      entity = QadEntity()
      # copio entitySet
      entitySet = QadEntitySet(self.entitySet)
      
      self.plugIn.beginEditCommand("Feature copied", entitySet.getLayerList())

      for layerEntitySet in entitySet.layerEntitySetList:
         layer = layerEntitySet.layer
         
         while len(layerEntitySet.featureIds) > 0:
            featureId = layerEntitySet.featureIds[0]
            # verifico se l'entità appartiene ad uno stile di quotatura
            dimEntity = QadDimStyles.getDimEntity(layer, featureId)
            
            f = layerEntitySet.getFeature(featureId)
            if f is None:
               del layerEntitySet.featureIds[0]
               continue

            # verifico se l'entità appartiene ad uno stile di quotatura
            dimEntity = QadDimStyles.getDimEntity(layer, f.id())
            if dimEntity is None:
               entity.set(layer, f.id())
               if qad_array_fun.arrayPolarEntity(self.plugIn, entity, self.basePt, self.centerPt, self.polarItemsNumber, \
                                                 self.polarAngleBetween, self.polarRows, self.distanceBetweenRows, self.itemsRotation, \
                                                 True, None) == False:
                  self.plugIn.destroyEditCommand()
                  return
               del layerEntitySet.featureIds[0] # la rimuovo da entitySet
            else:
               if qad_array_fun.arrayPolarEntity(self.plugIn, dimEntity, self.basePt, self.centerPt, self.polarItemsNumber, \
                                                 self.polarAngleBetween, self.polarRows, self.distanceBetweenRows, self.itemsRotation, \
                                                 True, None) == False:
                  self.plugIn.destroyEditCommand()
                  return
               dimEntitySet = dimEntity.getEntitySet()
               entitySet.subtract(dimEntitySet) # la rimuovo da entitySet
               
      if self.delOrigSelSet: # se devo rimuovere gli oggetti originali
         for layerEntitySet in self.entitySet.layerEntitySetList:
            # plugIn, layer, featureIds, refresh
            if qad_layer.deleteFeaturesToLayer(self.plugIn, layerEntitySet.layer, \
                                               layerEntitySet.featureIds, False) == False:
               self.plugIn.destroyEditCommand()
               return

      self.plugIn.endEditCommand()


   #============================================================================
   # setPathLinearObjectList
   #============================================================================
   def setPathLinearObjectList(self, entity, point):
      """
      Setta self.pathLinearObjectList che definisce la traiettoria
      """
      geom = self.layerToMapCoordinates(entity.layer, entity.getGeometry())
      # ritorna una tupla (<The squared cartesian distance>,
      #                    <minDistPoint>
      #                    <afterVertex>
      #                    <leftOf>)
      dummy = qad_utils.closestSegmentWithContext(point, geom)
      if dummy[2] is not None:
         # ritorna la sotto-geometria al vertice <atVertex> e la sua posizione nella geometria (0-based)
         subGeom, atSubGeom = qad_utils.getSubGeomAtVertex(geom, dummy[2])
         self.pathLinearObjectList.fromPolyline(subGeom.asPolyline())
         return True
      else:
         return False


   #============================================================================
   # setDistancesByPathItemNumberOnDivide
   #============================================================================
   def setDistancesByPathItemNumberOnDivide(self):
      # imposta le distanza dall'inizio della traccia e la distanza tra gli elementi
      # quando gli elementi devono essere distribuiti uniformemente
      self.distanceBetweenCols = self.pathLinearObjectList.length() / (self.pathItemsNumber + 1)
      self.distanceFromStartPt = self.distanceBetweenCols


   #============================================================================
   # setItemNumberByDistanceBetweenColsOnMeasure
   #============================================================================
   def setItemNumberByDistanceBetweenColsOnMeasure(self):
      # imposta le distanza dall'inizio della traccia e il numero di elementi
      # quando gli elementi non devono essere distribuiti uniformemente ma a partire dall'inizio della traccia
      self.pathItemsNumber = int(self.pathLinearObjectList.length() / self.distanceBetweenCols) + 1
      self.distanceFromStartPt = 0.0


   #============================================================================
   # waitForMainOptions
   #============================================================================
   def waitForMainOptions(self):          
      if self.arrayType == QadARRAYCommandClassSeriesTypeEnum.RECTANGLE:
         self.waitForRectangleArrayOptions()
      elif self.arrayType == QadARRAYCommandClassSeriesTypeEnum.PATH:
         self.waitForPathArrayOptions()
      elif self.arrayType == QadARRAYCommandClassSeriesTypeEnum.POLAR:
         self.waitForPolarArrayOptions()

      self.updatePointMapToolParams()


   #============================================================================
   # waitForArrayType
   #============================================================================
   def waitForArrayType(self):
      self.step = QadARRAYCommandClassStepEnum.ASK_FOR_ARRAYTYPE
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_array_maptool_ModeEnum.NONE)

      keyWords = QadMsg.translate("Command_ARRAY", "Rectangular") + "/" + \
                 QadMsg.translate("Command_ARRAY", "PAth") + "/" + \
                 QadMsg.translate("Command_ARRAY", "POlar")
      englishKeyWords = "Rectangular" + "/" + "PAth" + "/" + "POlar"

      if self.arrayType == QadARRAYCommandClassSeriesTypeEnum.RECTANGLE:
         self.defaultValue = QadMsg.translate("Command_ARRAY", "Rectangular")
      elif self.arrayType == QadARRAYCommandClassSeriesTypeEnum.PATH:
         self.defaultValue = QadMsg.translate("Command_ARRAY", "PAth")
      elif self.arrayType == QadARRAYCommandClassSeriesTypeEnum.POLAR:
         self.defaultValue = QadMsg.translate("Command_ARRAY", "POlar")
         
      prompt = QadMsg.translate("Command_ARRAY", "Enter array type [{0}] <{1}>: ").format(keyWords, self.defaultValue)
      
      keyWords += "_" + englishKeyWords
      # si appresta ad attendere un punto o enter o una parola chiave         
      # msg, inputType, default, keyWords, nessun controllo
      self.waitFor(prompt, \
                   QadInputTypeEnum.KEYWORDS, \
                   self.defaultValue, \
                   keyWords, QadInputModeEnum.NONE)      


   #============================================================================
   # waitForBasePt
   #============================================================================
   def waitForBasePt(self, nextStep = QadARRAYCommandClassStepEnum.ASK_FOR_BASE_PT):
      self.step = nextStep 
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_array_maptool_ModeEnum.ASK_FOR_BASE_PT)
      # si appresta ad attendere un punto
      self.waitForPoint(QadMsg.translate("Command_ARRAY", "Specify base point: "))


   #============================================================================
   # waitForItemsNumber
   #============================================================================
   def waitForItemsNumber(self):
      self.step = QadARRAYCommandClassStepEnum.ASK_FOR_ITEM_N
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_array_maptool_ModeEnum.NONE)

      if self.arrayType == QadARRAYCommandClassSeriesTypeEnum.PATH:
         keyWords = QadMsg.translate("Command_ARRAY", "Fill entire path")
         englishKeyWords = "Fill entire path"
         self.defaultValue = self.pathItemsNumber
         # si appresta ad attendere un numero intero
         prompt = QadMsg.translate("Command_ARRAY", "Number of Items to Array or [{0}] <{1}>: ").format(keyWords, str(self.defaultValue))
         keyWords += "_" + englishKeyWords
         inputType = QadInputTypeEnum.INT | QadInputTypeEnum.KEYWORDS
      elif self.arrayType == QadARRAYCommandClassSeriesTypeEnum.POLAR:
         # si appresta ad attendere un numero intero
         keyWords = ""
         self.defaultValue = self.polarItemsNumber
         prompt = QadMsg.translate("Command_ARRAY", "Number of Items to Array <{0}>: ").format(str(self.defaultValue))
         inputType = QadInputTypeEnum.INT
      
      # msg, inputType, default, keyWords, valori positivi
      self.waitFor(prompt, \
                   inputType, \
                   self.defaultValue, \
                   keyWords, \
                   QadInputModeEnum.NOT_ZERO | QadInputModeEnum.NOT_NEGATIVE)


   #============================================================================
   # waitForRows
   #============================================================================
   def waitForRows(self, nextStep):
      self.step = nextStep
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_array_maptool_ModeEnum.NONE)

      # si appresta ad attendere un numero intero
      msg = QadMsg.translate("Command_ARRAY", "Specify number of rows <{0}>: ")
      if self.arrayType == QadARRAYCommandClassSeriesTypeEnum.RECTANGLE:
         self.defaultValue = self.rectangleRows
      elif self.arrayType == QadARRAYCommandClassSeriesTypeEnum.PATH:
         self.defaultValue = self.pathRows
      elif self.arrayType == QadARRAYCommandClassSeriesTypeEnum.POLAR:
         self.defaultValue = self.polarRows
      prompt = msg.format(str(self.defaultValue))
      # msg, inputType, default, keyWords, valori positivi
      self.waitFor(prompt, \
                   QadInputTypeEnum.INT, \
                   self.defaultValue, \
                   "", \
                   QadInputModeEnum.NOT_ZERO | QadInputModeEnum.NOT_NEGATIVE)


   #============================================================================
   # waitForDistanceBetweenRows
   #============================================================================
   def waitForDistanceBetweenRows(self, totalOption, nextStep):
      self.step = nextStep
      self.getPointMapTool().setMode(Qad_array_maptool_ModeEnum.ASK_FOR_ROW_SPACE_FIRST_PT)

      self.defaultValue = self.distanceBetweenRows
      if self.arrayType == QadARRAYCommandClassSeriesTypeEnum.RECTANGLE:
         inputMode = QadInputModeEnum.NOT_ZERO
      elif self.arrayType == QadARRAYCommandClassSeriesTypeEnum.PATH:
         inputMode = QadInputModeEnum.NOT_ZERO
      elif self.arrayType == QadARRAYCommandClassSeriesTypeEnum.POLAR:
         inputMode = QadInputModeEnum.NOT_ZERO | QadInputModeEnum.NOT_NEGATIVE

      if totalOption:
         keyWords = QadMsg.translate("Command_ARRAY", "Total")
         englishKeyWords = "Total"
         prompt = QadMsg.translate("Command_ARRAY", "Specify distance between rows or [{0}] <{1}>: ").format(keyWords, str(self.defaultValue))
         keyWords += "_" + englishKeyWords
         inputType = QadInputTypeEnum.FLOAT | QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS
      else:
         prompt = QadMsg.translate("Command_ARRAY", "Specify distance between rows <{0}>: ").format(str(self.defaultValue))
         keyWords = ""
         inputType = QadInputTypeEnum.FLOAT | QadInputTypeEnum.POINT2D
      
      # si appresta ad attendere un punto, un numero reale o enter o una parola chiave
      # msg, inputType, default, keyWords, inputMode
      self.waitFor(prompt, \
                   inputType, \
                   self.defaultValue, \
                   keyWords, \
                   inputMode)
      

   #=========================================================================
   # waitForDistanceBetweenRows2Pt
   #=========================================================================
   def waitForDistanceBetweenRows2Pt(self, startPt):
      self.step = QadARRAYCommandClassStepEnum.ASK_FOR_ROW_SPACE_2PT

      if self.GetDistClass is not None:
         del self.GetDistClass
      self.GetDistClass = QadGetDistClass(self.plugIn)
      
      self.GetDistClass.dist = self.distanceBetweenRows
      self.GetDistClass.inputMode = QadInputModeEnum.NOT_ZERO
      self.GetDistClass.startPt = startPt
      self.GetDistClass.run()
         
   
   #============================================================================
   # waitForTotalDistanceRows
   #============================================================================
   def waitForTotalDistanceRows(self):
      self.step = QadARRAYCommandClassStepEnum.ASK_FOR_ROW_SPACE_TOT

      if self.arrayType == QadARRAYCommandClassSeriesTypeEnum.RECTANGLE:
         default = self.rectangleRows * self.distanceBetweenRows
         inputMode = QadInputModeEnum.NOT_ZERO
      elif self.arrayType == QadARRAYCommandClassSeriesTypeEnum.PATH:
         default = self.pathRows * self.distanceBetweenRows
         inputMode = QadInputModeEnum.NOT_ZERO
      elif self.arrayType == QadARRAYCommandClassSeriesTypeEnum.POLAR:
         default = self.polarRows * self.distanceBetweenRows 
         inputMode = QadInputModeEnum.NOT_ZERO | QadInputModeEnum.NOT_NEGATIVE
      
      if self.GetDistClass is not None:
         del self.GetDistClass
      self.GetDistClass = QadGetDistClass(self.plugIn)
      prompt = QadMsg.translate("Command_ARRAY", "Specifies the total distance between the start and end row <{0}>: ")
      self.GetDistClass.msg = prompt.format(str(default))
      self.GetDistClass.dist = default
      self.GetDistClass.inputMode = inputMode
      self.GetDistClass.run()


   #============================================================================
   # waitForDelOrigObjs
   #============================================================================
   def waitForDelOrigObjs(self):
      self.step = QadARRAYCommandClassStepEnum.ASK_FOR_DEL_ORIG_OBJS
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_array_maptool_ModeEnum.NONE)

      keyWords = QadMsg.translate("QAD", "Yes") + "/" + QadMsg.translate("QAD", "No")
      self.defaultValue = QadMsg.translate("QAD", "Yes")
      prompt = QadMsg.translate("Command_ARRAY", "Delete source objects of the array ? [{0}] <{1}>: ").format(keyWords, self.defaultValue)
      
      englishKeyWords = "Yes" + "/" + "No"
      keyWords += "_" + englishKeyWords

      # msg, inputType, default, keyWords, nessun controllo
      self.waitFor(prompt, \
                   QadInputTypeEnum.KEYWORDS, \
                   self.defaultValue, \
                   keyWords, QadInputModeEnum.NONE)


   #============================================================================
   # waitForItemsRotation
   #============================================================================
   def waitForItemsRotation(self):
      self.step = QadARRAYCommandClassStepEnum.ASK_FOR_ITEM_ROTATION
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_array_maptool_ModeEnum.NONE)

      keyWords = QadMsg.translate("QAD", "Yes") + "/" + QadMsg.translate("QAD", "No")
      if self.itemsRotation:
         self.defaultValue = QadMsg.translate("QAD", "Yes")
      else:
         self.defaultValue = QadMsg.translate("QAD", "No")
         
      if self.arrayType == QadARRAYCommandClassSeriesTypeEnum.RECTANGLE:
         prompt = QadMsg.translate("Command_ARRAY", "Rotate objects as they are arrayed ? [{0}] <{1}>: ").format(keyWords, self.defaultValue)
      elif self.arrayType == QadARRAYCommandClassSeriesTypeEnum.PATH:
         prompt = QadMsg.translate("Command_ARRAY", "Align arrayed items to the path ? [{0}] <{1}>: ").format(keyWords, self.defaultValue)
      elif self.arrayType == QadARRAYCommandClassSeriesTypeEnum.POLAR:
         prompt = QadMsg.translate("Command_ARRAY", "Rotate objects as they are arrayed ? [{0}] <{1}>: ").format(keyWords, self.defaultValue)

      englishKeyWords = "Yes" + "/" + "No"
      keyWords += "_" + englishKeyWords
         
      # msg, inputType, default, keyWords, nessun controllo
      self.waitFor(prompt, \
                   QadInputTypeEnum.KEYWORDS, \
                   self.defaultValue, \
                   keyWords, QadInputModeEnum.NONE)


   #============================================================================
   # SERIE RETTANGOLARE - INIZIO
   #============================================================================


   #============================================================================
   # waitForRectangleArrayOptions
   #============================================================================
   def waitForRectangleArrayOptions(self):
      self.step = QadARRAYCommandClassStepEnum.ASK_FOR_MAIN_OPTIONS
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_array_maptool_ModeEnum.NONE)

      keyWords = QadMsg.translate("Command_ARRAY", "Base point") + "/" + \
                 QadMsg.translate("Command_ARRAY", "Angle") + "/" + \
                 QadMsg.translate("Command_ARRAY", "COUnt") + "/" + \
                 QadMsg.translate("Command_ARRAY", "Spacing") + "/" + \
                 QadMsg.translate("Command_ARRAY", "Columns") + "/" + \
                 QadMsg.translate("Command_ARRAY", "Rows") + "/" + \
                 QadMsg.translate("Command_ARRAY", "rotate Items") + "/" + \
                 QadMsg.translate("Command_ARRAY", "eXit")
      englishKeyWords = "Base point" + "/" + "Angle" + "/" + "COUnt" + "/" + "Spacing" + "/" + \
                        "Columns" + "/" + "Rows" + "/" + "rotate Items" + "/" + "eXit"

      self.defaultValue = QadMsg.translate("Command_ARRAY", "eXit")         
      prompt = QadMsg.translate("Command_ARRAY", "Select an option to edit array or [{0}] <{1}>: ").format(keyWords, self.defaultValue)
      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, \
                   self.defaultValue, \
                   keyWords, QadInputModeEnum.NONE)


   #============================================================================
   # waitForRectangleAngle
   #============================================================================
   def waitForRectangleAngle(self):
      self.step = QadARRAYCommandClassStepEnum.ASK_FOR_ANGLE
      if self.GetAngleClass is not None:
         del self.GetAngleClass                  
      # si appresta ad attendere l'angolo di rotazione                      
      self.GetAngleClass = QadGetAngleClass(self.plugIn)
      prompt = QadMsg.translate("Command_ARRAY", "Specify the angle of rotation for the row axis <{0}>: ")
      self.GetAngleClass.msg = prompt.format(str(qad_utils.toDegrees(self.rectangleAngle)))
      self.GetAngleClass.angle = self.rectangleAngle
      self.GetAngleClass.run()
      return False

   
   #============================================================================
   # waitForRectangleColumns
   #============================================================================
   def waitForRectangleColumns(self, nextStep):
      self.step = nextStep
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_array_maptool_ModeEnum.NONE)

      # optionFrom può essere ASK_FOR_COLUMN_COUNT o ASK_FOR_COLUMN_N
      self.defaultValue = self.rectangleCols
      # si appresta ad attendere un numero intero
      msg = QadMsg.translate("Command_ARRAY", "Specify number of columns <{0}>: ")
      # msg, inputType, default, keyWords, valori positivi
      self.waitFor(msg.format(str(self.defaultValue)), \
                   QadInputTypeEnum.INT, \
                   self.defaultValue, \
                   "", \
                   QadInputModeEnum.NOT_ZERO | QadInputModeEnum.NOT_NEGATIVE)


   #============================================================================
   # waitForRectangleColumnsSpacing
   #============================================================================
   def waitForRectangleColumnsSpacing(self):
      self.step = QadARRAYCommandClassStepEnum.ASK_FOR_COLUMN_SPACE_OR_CELL
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_array_maptool_ModeEnum.ASK_FOR_COLUMN_SPACE_FIRST_PT)

      self.defaultValue = self.distanceBetweenCols
      keyWords = QadMsg.translate("Command_ARRAY", "Unit cell")
      englishKeyWords = "Unit cell"
      prompt = QadMsg.translate("Command_ARRAY", "Specify distance between columns or [{0}] <{1}>: ")     
      prompt = prompt.format(keyWords, str(self.defaultValue))
      keyWords += "_" + englishKeyWords
      
      # si appresta ad attendere un punto, un numero reale o enter o una parola chiave
      # msg, inputType, default, keyWords, valori positivi
      self.waitFor(prompt, \
                   QadInputTypeEnum.FLOAT | QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS, \
                   self.defaultValue, \
                   keyWords, \
                   QadInputModeEnum.NOT_ZERO)


   #============================================================================
   # waitForRectangleColumnsSpacing2Pt
   #============================================================================
   def waitForRectangleColumnsSpacing2Pt(self, startPt):
      self.step = QadARRAYCommandClassStepEnum.ASK_FOR_COLUMN_SPACE_2PT
      
      if self.GetDistClass is not None:
         del self.GetDistClass
      self.GetDistClass = QadGetDistClass(self.plugIn)
      self.GetDistClass.dist = self.distanceBetweenCols
      self.GetDistClass.inputMode = QadInputModeEnum.NOT_ZERO
      self.GetDistClass.startPt = startPt
      self.GetDistClass.run()


   #============================================================================
   # waitForRectangleTotalDistanceCols
   #============================================================================
   def waitForRectangleTotalDistanceCols(self):
      self.step = QadARRAYCommandClassStepEnum.ASK_FOR_COLUMN_SPACE_TOT
      
      if self.GetDistClass is not None:
         del self.GetDistClass
      self.GetDistClass = QadGetDistClass(self.plugIn)
      prompt = QadMsg.translate("Command_ARRAY", "Specifies the total distance between the start and end columns <{0}>: ")
      default = self.rectangleCols * self.distanceBetweenCols
      self.GetDistClass.msg = prompt.format(str(default))
      self.GetDistClass.dist = default
      self.GetDistClass.inputMode = QadInputModeEnum.NOT_ZERO
      self.GetDistClass.run()


   #============================================================================
   # waitForRectangleDistanceBetweenCols
   #============================================================================
   def waitForRectangleDistanceBetweenCols(self, totalOption):
      self.step = QadARRAYCommandClassStepEnum.ASK_FOR_COLUMN_SPACE_OR_TOT
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_array_maptool_ModeEnum.ASK_FOR_COLUMN_SPACE_FIRST_PT)

      self.defaultValue = self.distanceBetweenCols

      if totalOption:
         keyWords = QadMsg.translate("Command_ARRAY", "Total")
         englishKeyWords = "Total"
         prompt = QadMsg.translate("Command_ARRAY", "Specify distance between columns or [{0}] <{1}>: ").format(keyWords, str(self.defaultValue))
         keyWords += "_" + englishKeyWords
         inputType = QadInputTypeEnum.FLOAT | QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS
      else:
         prompt = QadMsg.translate("Command_ARRAY", "Specify distance between columns <{0}>: ").format(str(self.defaultValue))
         keyWords = ""
         inputType = QadInputTypeEnum.FLOAT | QadInputTypeEnum.POINT2D
      
      # si appresta ad attendere un punto, un numero reale o enter o una parola chiave
      # msg, inputType, default, keyWords, valori positivi
      self.waitFor(prompt, \
                   inputType, \
                   self.defaultValue, \
                   keyWords, \
                   QadInputModeEnum.NOT_ZERO)
      
      
   #============================================================================
   # waitForRectangleFirstCellCorner
   #============================================================================
   def waitForRectangleFirstCellCorner(self):
      self.step = QadARRAYCommandClassStepEnum.ASK_FOR_1PT_CELL
      # si appresta ad attendere un punto
      self.waitForPoint(QadMsg.translate("Command_ARRAY", "Specify first cell corner: "))
      
      
   #============================================================================
   # waitForRectangleSecondCellCorner
   #============================================================================
   def waitForRectangleSecondCellCorner(self):
      self.step = QadARRAYCommandClassStepEnum.ASK_FOR_2PT_CELL
      # imposto il map tool
      self.getPointMapTool().firstPt = self.firstPt
      self.getPointMapTool().setMode(Qad_array_maptool_ModeEnum.ASK_FOR_2PT_CELL)
      # si appresta ad attendere un punto
      self.waitForPoint(QadMsg.translate("Command_ARRAY", "Specify second cell corner: "))


   #============================================================================
   # SERIE RETTANGOLARE - FINE
   # SERIE TRAIETTORIA  - INIZIO
   #============================================================================


   #============================================================================
   # waitForPathObject
   #============================================================================
   def waitForPathObject(self, msgMapTool, msg):
      if self.entSelClass is not None:
         del self.entSelClass
      
      self.step = QadARRAYCommandClassStepEnum.ASK_FOR_PATH_OBJ
      
      self.entSelClass = QadEntSelClass(self.plugIn)
      self.entSelClass.msg = QadMsg.translate("Command_ARRAY", "Select the object to use for the path of the array: ")
      # scarto la selezione di punti e quote
      self.entSelClass.checkPointLayer = False
      self.entSelClass.checkLineLayer = True
      self.entSelClass.checkPolygonLayer = True
      self.entSelClass.checkDimLayers = False

      self.entSelClass.run(msgMapTool, msg)
      

   #============================================================================
   # waitForPathArrayOptions
   #============================================================================
   def waitForPathArrayOptions(self):
      self.step = QadARRAYCommandClassStepEnum.ASK_FOR_MAIN_OPTIONS
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_array_maptool_ModeEnum.NONE)

      keyWords = QadMsg.translate("Command_ARRAY", "Method") + "/" + \
                 QadMsg.translate("Command_ARRAY", "Base point") + "/" + \
                 QadMsg.translate("Command_ARRAY", "Tangent direction") + "/" + \
                 QadMsg.translate("Command_ARRAY", "Items") + "/" + \
                 QadMsg.translate("Command_ARRAY", "Rows") + "/" + \
                 QadMsg.translate("Command_ARRAY", "Align items") + "/" + \
                 QadMsg.translate("Command_ARRAY", "eXit")
      englishKeyWords = "Method" + "/" + "Base point" + "/" + "Tangent direction" + "/" + "Items" + "/" + \
                        "Rows" + "/" + "Align items" + "/" + "eXit"

      self.defaultValue = QadMsg.translate("Command_ARRAY", "eXit")         
      prompt = QadMsg.translate("Command_ARRAY", "Select an option to edit array or [{0}] <{1}>: ").format(keyWords, self.defaultValue)
      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, \
                   self.defaultValue, \
                   keyWords, QadInputModeEnum.NONE)


   #============================================================================
   # waitForPathMethod
   #============================================================================
   def waitForPathMethod(self):
      self.step = QadARRAYCommandClassStepEnum.ASK_FOR_PATH_METHOD

      keyWords = QadMsg.translate("Command_ARRAY", "Divide") + "/" + QadMsg.translate("Command_ARRAY", "Measure")
      if self.pathMethod == QadARRAYCommandClassPathMethodTypeEnum.DIVIDE:
         self.defaultValue = QadMsg.translate("Command_ARRAY", "Divide")
      elif self.pathMethod == QadARRAYCommandClassPathMethodTypeEnum.MEASURE:
         self.defaultValue = QadMsg.translate("Command_ARRAY", "Measure")
      prompt = QadMsg.translate("Command_ARRAY", "Specify path method [{0}] <{1}>: ").format(keyWords, self.defaultValue)
      
      englishKeyWords = "Divide" + "/" + "Measure"
      keyWords += "_" + englishKeyWords

      # si appresta ad attendere enter o una parola chiave
      # msg, inputType, default, keyWords, nessun controllo
      self.waitFor(prompt, \
                   QadInputTypeEnum.KEYWORDS, \
                   self.defaultValue, \
                   keyWords, QadInputModeEnum.NONE)


   #============================================================================
   # waitForPathTangentDirection
   #============================================================================
   def waitForPathTangentDirection(self):
      self.step = QadARRAYCommandClassStepEnum.ASK_FOR_TAN_DIRECTION
      
      if self.GetAngleClass is not None:
         del self.GetAngleClass                  
      # si appresta ad attendere l'angolo di rotazione                      
      self.GetAngleClass = QadGetAngleClass(self.plugIn)
      prompt = QadMsg.translate("Command_ARRAY", "Specify the first point for array tangent direction: ")
      self.GetAngleClass.msg = prompt.format(str(qad_utils.toDegrees(self.pathTangentDirection)))
      self.GetAngleClass.angle = self.pathTangentDirection
      self.GetAngleClass.run()
      return False


   #============================================================================
   # waitForPathDistanceBetweenItems
   #============================================================================
   def waitForPathDistanceBetweenItems(self):
      self.step = QadARRAYCommandClassStepEnum.ASK_FOR_ITEM_SPACE
      
      if self.GetDistClass is not None:
         del self.GetDistClass
      self.GetDistClass = QadGetDistClass(self.plugIn)
      prompt = QadMsg.translate("Command_ARRAY", "Specify distance between items along path <{0}>: ")
      self.GetDistClass.msg = prompt.format(str(self.distanceBetweenCols))
      self.GetDistClass.dist = self.distanceBetweenCols
      self.GetDistClass.inputMode = QadInputModeEnum.NOT_ZERO | QadInputModeEnum.NOT_NEGATIVE
      self.GetDistClass.run()


   #============================================================================
   # SERIE TRAIETTORIA  - FINE
   # SERIE POLARE       - INIZIO
   #============================================================================


   #============================================================================
   # waitForPolarCenterPt
   #============================================================================
   def waitForPolarCenterPt(self):
      self.step = QadARRAYCommandClassStepEnum.ASK_FOR_CENTER_PT

      keyWords = QadMsg.translate("Command_ARRAY", "Base point")
      englishKeyWords = "Base point"
      prompt = QadMsg.translate("Command_ARRAY", "Specify center point of array or [{0}]: ").format(keyWords)
      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)

   
   #============================================================================
   # waitForPolarArrayOptions
   #============================================================================
   def waitForPolarArrayOptions(self):
      self.step = QadARRAYCommandClassStepEnum.ASK_FOR_MAIN_OPTIONS
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_array_maptool_ModeEnum.NONE)

      keyWords = QadMsg.translate("Command_ARRAY", "Base point") + "/" + \
                 QadMsg.translate("Command_ARRAY", "Items") + "/" + \
                 QadMsg.translate("Command_ARRAY", "Angle between") + "/" + \
                 QadMsg.translate("Command_ARRAY", "Fill angle") + "/" + \
                 QadMsg.translate("Command_ARRAY", "ROWs") + "/" + \
                 QadMsg.translate("Command_ARRAY", "Rotate items") + "/" + \
                 QadMsg.translate("Command_ARRAY", "eXit")
      englishKeyWords = "Base point" + "/" + "Items" + "/" + "Angle between" + "/" + "Angle between" + "/" + \
                        "Fill angle" + "/" + "ROWs" + "/" + "Rotate items" + "/" + "eXit"

      self.defaultValue = QadMsg.translate("Command_ARRAY", "eXit")         
      prompt = QadMsg.translate("Command_ARRAY", "Select an option to edit array or [{0}] <{1}>: ").format(keyWords, self.defaultValue)
      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, \
                   self.defaultValue, \
                   keyWords, QadInputModeEnum.NONE)      

   
   #============================================================================
   # waitForPolarAngleBetween
   #============================================================================
   def waitForPolarAngleBetween(self):
      self.step = QadARRAYCommandClassStepEnum.ASK_FOR_ANGLE_BETWEEN_ITEMS
      
      if self.GetAngleClass is not None:
         del self.GetAngleClass                  
      # si appresta ad attendere l'angolo di rotazione                      
      self.GetAngleClass = QadGetAngleClass(self.plugIn)
      prompt = QadMsg.translate("Command_ARRAY", "Specify the angle between items <{0}>: ")
      self.GetAngleClass.msg = prompt.format(str(qad_utils.toDegrees(self.polarAngleBetween)))
      self.GetAngleClass.angle = self.polarAngleBetween
      self.GetAngleClass.run()
      return False

   
   #============================================================================
   # waitForPolarAngleBetween
   #============================================================================
   def waitForPolarFillAngle(self):
      self.step = QadARRAYCommandClassStepEnum.ASK_FOR_FULL_ANGLE
      
      if self.GetAngleClass is not None:
         del self.GetAngleClass                  
      # si appresta ad attendere l'angolo di rotazione                      
      self.GetAngleClass = QadGetAngleClass(self.plugIn)
      default = self.polarItemsNumber * self.polarAngleBetween
      prompt = QadMsg.translate("Command_ARRAY", "Specify angle to fill (+ = CCW, - = CW) <{0}>: ")
      self.GetAngleClass.msg = prompt.format(str(qad_utils.toDegrees(default)))
      self.GetAngleClass.angle = default
      self.GetAngleClass.run()
      return False


   #============================================================================
   # SERIE POLARE - FINE
   #============================================================================


   #============================================================================
   # 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 == QadARRAYCommandClassStepEnum.ASK_FOR_SELSET: # inizio del comando
         if self.entitySet.count() > 0: # se era già stato impostato da codice tramite "self.setEntitySet"
            self.waitForArrayType()
            return False
            
         if self.SSGetClass.run(msgMapTool, msg) == True:
            if self.SSGetClass.entitySet.count() == 0:
               return True # fine comando
            self.setEntitySet(self.SSGetClass.entitySet)
            
            del self.SSGetClass
            self.SSGetClass = None
            
            self.waitForArrayType()
            self.step = -1 * self.step # trucchetto per prendere il map tool base
            self.getPointMapTool().refreshSnapType() # aggiorno lo snapType che può essere variato dal maptool di selezione entità                    
            self.step = -1 * self.step # trucchetto per prendere il map tool base
            
         return False
         
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL TIPO DI SERIE (da step = ASK_FOR_SELSET)
      elif self.step == QadARRAYCommandClassStepEnum.ASK_FOR_ARRAYTYPE: # dopo aver atteso una parola chiave si riavvia il comando
         if msgMapTool == True: # il punto arriva da una selezione grafica
            if self.getPointMapTool().rightButton == True: # se usato il tasto destro del mouse
               value = self.defaultValue 
            else:
               self.setMapTool(self.getPointMapTool()) # riattivo il maptool
               return False
         else: # la parola chiave arriva come parametro della funzione
            value = msg

         if type(value) == unicode:
            if value == QadMsg.translate("Command_ARRAY", "Rectangular") or value == "Rectangular":
               self.arrayType = QadARRAYCommandClassSeriesTypeEnum.RECTANGLE
               self.plugIn.setLastArrayType_array(self.arrayType)
               self.waitForMainOptions()
            elif value == QadMsg.translate("Command_ARRAY", "PAth") or value == "PAth":
               self.arrayType = QadARRAYCommandClassSeriesTypeEnum.PATH
               self.plugIn.setLastArrayType_array(self.arrayType)
               self.waitForPathObject(msgMapTool, msg)
            elif value == QadMsg.translate("Command_ARRAY", "POlar") or value == "POlar":
               self.arrayType = QadARRAYCommandClassSeriesTypeEnum.POLAR
               self.plugIn.setLastArrayType_array(self.arrayType)
               self.waitForPolarCenterPt()
         
         return False 
         
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DI UN OPZIONE DAL MENU PRINCIPALE (da step = ASK_FOR_ARRAYTYPE da tutte le opzioni)
      elif self.step == QadARRAYCommandClassStepEnum.ASK_FOR_MAIN_OPTIONS: # dopo aver atteso un punto o una parola chiave si riavvia il comando
         if msgMapTool == True: # il punto arriva da una selezione grafica
            if self.getPointMapTool().rightButton == True: # se usato il tasto destro del mouse
               value = self.defaultValue 
            else:
               self.setMapTool(self.getPointMapTool()) # riattivo il maptool
               return False
         else: # il punto arriva come parametro della funzione
            value = msg

         if value is None:
            value = QadMsg.translate("Command_ARRAY", "eXit")
         
         if type(value) == unicode:
            if self.arrayType == QadARRAYCommandClassSeriesTypeEnum.RECTANGLE:
               if value ==  QadMsg.translate("Command_ARRAY", "Base point") or value == "Base point":
                  self.waitForBasePt()
               elif value == QadMsg.translate("Command_ARRAY", "Angle") or value == "Angle":
                  self.waitForRectangleAngle()
               elif value == QadMsg.translate("Command_ARRAY", "COUnt") or value == "COUnt":
                  self.waitForRectangleColumns(QadARRAYCommandClassStepEnum.ASK_FOR_COLUMN_COUNT)
               elif value == QadMsg.translate("Command_ARRAY", "Spacing") or value == "Spacing":
                  self.waitForRectangleColumnsSpacing()
               elif value == QadMsg.translate("Command_ARRAY", "Columns") or value == "Columns":
                  self.waitForRectangleColumns(QadARRAYCommandClassStepEnum.ASK_FOR_COLUMN_N)
               elif value == QadMsg.translate("Command_ARRAY", "Rows") or value == "Rows":
                  self.waitForRows(QadARRAYCommandClassStepEnum.ASK_FOR_ROW_N)
               elif value ==  QadMsg.translate("Command_ARRAY", "rotate Items") or value == "rotate Items":
                  self.waitForItemsRotation()
               elif value == QadMsg.translate("Command_ARRAY", "eXit") or value == "eXit":
                  if self.delObj == QadDELOBJEnum.ASK_FOR_DELETE_ALL:
                     self.waitForDelOrigObjs()
                  else:                  
                     self.doRectangleArray()
                     return True # fine comando
               
            elif self.arrayType == QadARRAYCommandClassSeriesTypeEnum.PATH:
               if value == QadMsg.translate("Command_ARRAY", "Method") or value == "Method":
                  self.waitForPathMethod()
               elif value ==  QadMsg.translate("Command_ARRAY", "Base point") or value == "Base point":
                  self.waitForBasePt()
               elif value ==  QadMsg.translate("Command_ARRAY", "Tangent direction") or value == "Tangent direction":
                  self.waitForPathTangentDirection()
               elif value ==  QadMsg.translate("Command_ARRAY", "Items") or value == "Items":
                  if self.pathMethod == QadARRAYCommandClassPathMethodTypeEnum.MEASURE:
                     self.waitForPathDistanceBetweenItems()
                  elif self.pathMethod == QadARRAYCommandClassPathMethodTypeEnum.DIVIDE:
                     self.waitForItemsNumber()
               elif value ==  QadMsg.translate("Command_ARRAY", "Rows") or value == "Rows":
                  self.waitForRows(QadARRAYCommandClassStepEnum.ASK_FOR_ROW_N)
               elif value ==  QadMsg.translate("Command_ARRAY", "Align items") or value == "Align items":
                  self.waitForItemsRotation()
               elif value == QadMsg.translate("Command_ARRAY", "eXit") or value == "eXit":
                  if self.delObj == QadDELOBJEnum.ASK_FOR_DELETE_ALL:
                     self.waitForDelOrigObjs()
                  else:                  
                     self.doPathArray()
                     return True # fine comando
                  
            elif self.arrayType == QadARRAYCommandClassSeriesTypeEnum.POLAR:
               if value ==  QadMsg.translate("Command_ARRAY", "Base point") or value == "Base point":
                  self.waitForBasePt()
               elif value ==  QadMsg.translate("Command_ARRAY", "Items") or value == "Items":
                  self.waitForItemsNumber()
               elif value ==  QadMsg.translate("Command_ARRAY", "Angle between") or value == "Angle between":
                  self.waitForPolarAngleBetween()
               elif value ==  QadMsg.translate("Command_ARRAY", "Fill angle") or value == "Fill angle":
                  self.waitForPolarFillAngle()
               elif value ==  QadMsg.translate("Command_ARRAY", "ROWs") or value == "ROWs":
                  self.waitForRows(QadARRAYCommandClassStepEnum.ASK_FOR_ROW_N)
               elif value ==  QadMsg.translate("Command_ARRAY", "Rotate items") or value == "Rotate items":
                  self.waitForItemsRotation()
               elif value == QadMsg.translate("Command_ARRAY", "eXit") or value == "eXit":
                  if self.delObj == QadDELOBJEnum.ASK_FOR_DELETE_ALL:
                     self.waitForDelOrigObjs()
                  else:                  
                     self.doPolarArray()
                     return True # fine comando                  
         elif type(value) == QgsPoint: # se é stato indicato un punto
            pass
         
         return False


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL PUNTO BASE (da step = ASK_FOR_MAIN_OPTIONS)
      elif self.step == QadARRAYCommandClassStepEnum.ASK_FOR_BASE_PT: # 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
                  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.set(value.x(), value.y())

         self.waitForMainOptions()
         return False


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DI CANCELLAZIONE DEGLI OGGETTI ORIGINALI (da step = ASK_FOR_MAIN_OPTIONS)
      elif self.step == QadARRAYCommandClassStepEnum.ASK_FOR_DEL_ORIG_OBJS: # dopo aver atteso una parola chiave si riavvia il comando
         if msgMapTool == True: # il punto arriva da una selezione grafica
            if self.getPointMapTool().rightButton == True: # se usato il tasto destro del mouse
               value = self.defaultValue 
            else:
               self.setMapTool(self.getPointMapTool()) # riattivo il maptool
               return False
         else:
            # la parola chiave arriva come parametro della funzione
            value = msg

         if type(value) == unicode:
            if value == QadMsg.translate("QAD", "Yes") or value == "Yes":
               self.delOrigSelSet = True
            else:
               self.delOrigSelSet = False

            if self.arrayType == QadARRAYCommandClassSeriesTypeEnum.RECTANGLE:
               self.doRectangleArray()
            elif self.arrayType == QadARRAYCommandClassSeriesTypeEnum.PATH:
               self.doPathArray()
            elif self.arrayType == QadARRAYCommandClassSeriesTypeEnum.POLAR:
               self.doPolarArray()

            return True
         
         return False 


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DELL'ANGOLO DELLA SERIE (da step = ASK_FOR_MAIN_OPTIONS)
      #=========================================================================
      elif self.step == QadARRAYCommandClassStepEnum.ASK_FOR_ANGLE:
         if self.GetAngleClass.run(msgMapTool, msg) == True:
            if self.GetAngleClass.angle is not None:
               self.rectangleAngle = self.GetAngleClass.angle
               self.plugIn.setLastRectangleAngle_array(self.rectangleAngle)
               self.plugIn.setLastRot(self.rectangleAngle)
            self.waitForMainOptions()
            
         return False


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL NUMERO DELLE COLONNE DELLA SERIE RETTANGOLO OPZIONE COUNT (da step = ASK_FOR_MAIN_OPTIONS)
      #=========================================================================
      elif self.step == QadARRAYCommandClassStepEnum.ASK_FOR_COLUMN_COUNT: # dopo aver atteso un numero intero si riavvia il comando
         if msgMapTool == True: # il punto arriva da una selezione grafica
            if self.getPointMapTool().rightButton == True: # se usato il tasto destro del mouse
               value = self.defaultValue 
            else:
               self.setMapTool(self.getPointMapTool()) # riattivo il maptool
               return False
         else:
            # il numero di colonne arriva come parametro della funzione
            value = msg

         maxArray = QadVariables.get(QadMsg.translate("Environment variables", "MAXARRAY"))
         if value * self.rectangleRows > maxArray:
            errMsg = QadMsg.translate("Command_ARRAY", "\nThe array size can't be greater than {0} elements. See MAXARRAY system variable.")
            self.showErr(errMsg.format(str(maxArray)))
         else:
            self.rectangleCols = value
            self.plugIn.setLastRectangleCols_array(self.rectangleCols)
            self.updatePointMapToolParams()
            self.waitForRows(QadARRAYCommandClassStepEnum.ASK_FOR_ROW_COUNT)
         return False


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL NUMERO DI RIGHE DELLA SERIE RETTANGOLO OPZIONE COUNT (da step = ASK_FOR_COLUMN_N)
      #=========================================================================
      elif self.step == QadARRAYCommandClassStepEnum.ASK_FOR_ROW_COUNT: # dopo aver atteso un numero intero si riavvia il comando
         if msgMapTool == True: # il punto arriva da una selezione grafica
            if self.getPointMapTool().rightButton == True: # se usato il tasto destro del mouse
               value = self.defaultValue 
            else:
               self.setMapTool(self.getPointMapTool()) # riattivo il maptool
               return False
         else:
            # il numero di righe arriva come parametro della funzione
            value = msg

         maxArray = QadVariables.get(QadMsg.translate("Environment variables", "MAXARRAY"))
         if value * self.rectangleCols > maxArray:
            errMsg = QadMsg.translate("Command_ARRAY", "\nThe array size can't be greater than {0} elements. See MAXARRAY system variable.")
            self.showErr(errMsg.format(str(maxArray)))
         else:
            self.rectangleRows = value
            self.plugIn.setLastRectangleRows_array(self.rectangleRows)
            self.waitForMainOptions()
         return False


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DELLA DISTANZA TRA COLONNE (da step = ASK_FOR_MAIN_OPTIONS)
      elif self.step == QadARRAYCommandClassStepEnum.ASK_FOR_COLUMN_SPACE_OR_CELL: # dopo aver atteso un punto, un numero 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
                  value = self.defaultValue 
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False
            else:
               value = self.getPointMapTool().point
         else: # il punto arriva come parametro della funzione
            value = msg

         if type(value) == QgsPoint: # se é stato inserito il primo punto per misurare la distanza tra colonne
            self.waitForRectangleColumnsSpacing2Pt(value)
         elif type(value) == float: # se é stato inserita la distanza
            self.distanceBetweenCols = value
            self.updatePointMapToolParams()
            self.waitForDistanceBetweenRows(False, QadARRAYCommandClassStepEnum.ASK_FOR_ROW_SPACE) # senza opzione di "totale"
         elif type(value) == unicode:
            if value == QadMsg.translate("Command_ARRAY", "Unit cell") or value == "Unit cell":
               self.waitForRectangleFirstCellCorner()
            
         return False


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL SECONDO PT PER MISURARE LA DISTANZA TRA COLONNE (da step = ASK_FOR_COLUMN_SPACE_OR_CELL)
      elif self.step == QadARRAYCommandClassStepEnum.ASK_FOR_COLUMN_SPACE_2PT: # dopo aver atteso un punto si riavvia il comando
         if self.GetDistClass.run(msgMapTool, msg) == True:
            if self.GetDistClass.dist is not None:
               self.distanceBetweenCols = self.GetDistClass.dist

            del self.GetDistClass
            self.GetDistClass = None
            
            self.updatePointMapToolParams()
            self.waitForDistanceBetweenRows(False, QadARRAYCommandClassStepEnum.ASK_FOR_ROW_SPACE) # senza opzione di "totale"
         return False # fine comando


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DELLA DISTANZA TRA RIGHE (da step = ASK_FOR_COLUMN_SPACE_OR_CELL)
      elif self.step == QadARRAYCommandClassStepEnum.ASK_FOR_ROW_SPACE: # 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
                  value = self.defaultValue 
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False
            else:
               value = self.getPointMapTool().point
         else: # il punto arriva come parametro della funzione
            value = msg

         if type(value) == QgsPoint: # se é stato inserito il primo punto per misurare la distanza tra righe
            self.waitForDistanceBetweenRows2Pt(value)
         elif type(value) == float: # se é stato inserita la distanza
            self.distanceBetweenRows = value
            self.waitForMainOptions()
         return False # fine comando


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL SECONDO PT PER MISURARE LA DISTANZA TRA RIGHE (da step = ASK_FOR_ROW_SPACE)
      elif self.step == QadARRAYCommandClassStepEnum.ASK_FOR_ROW_SPACE_2PT: # dopo aver atteso un punto si riavvia il comando
         if self.GetDistClass.run(msgMapTool, msg) == True:
            if self.GetDistClass.dist is not None:
               self.distanceBetweenRows = self.GetDistClass.dist
               
            del self.GetDistClass
            self.GetDistClass = None
            self.waitForMainOptions()
         return False # fine comando


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL PRIMO ANGOLO DELLA CELLA (da step = ASK_FOR_COLUMN_SPACE_OR_CELL)
      elif self.step == QadARRAYCommandClassStepEnum.ASK_FOR_1PT_CELL: # 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
                  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: # se é stato inserito il primo punto per misurare la distanza tra righe
            self.firstPt.set(value.x(), value.y())
            self.waitForRectangleSecondCellCorner()
         return False


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL SECONDO ANGOLO DELLA CELLA (da step = ASK_FOR_1PT_CELL)
      elif self.step == QadARRAYCommandClassStepEnum.ASK_FOR_2PT_CELL: # 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
                  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: # se é stato inserito il primo punto per misurare la distanza tra righe
            if (value.y() - self.firstPt.y()) == 0 or (value.x() - self.firstPt.x()) == 0:
               self.showErr(QadMsg.translate("Command_ARRAY", "\nCell size must be greater than 0."))
            else:
               self.distanceBetweenRows = value.y() - self.firstPt.y()
               self.distanceBetweenCols = value.x() - self.firstPt.x()
               self.waitForMainOptions()
         else:
            self.waitForMainOptions()
            
         return False


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL NUMERO DELLE COLONNE DELLA SERIE RETTANGOLO OPZIONE COLUMN (da step = ASK_FOR_MAIN_OPTIONS)
      #=========================================================================
      elif self.step == QadARRAYCommandClassStepEnum.ASK_FOR_COLUMN_N: # dopo aver atteso un numero intero si riavvia il comando
         if msgMapTool == True: # il punto arriva da una selezione grafica
            if self.getPointMapTool().rightButton == True: # se usato il tasto destro del mouse
               value = self.defaultValue 
            else:
               self.setMapTool(self.getPointMapTool()) # riattivo il maptool
               return False
         else:
            # il numero di righe arriva come parametro della funzione
            value = msg

         # il numero delle colonnne arriva come parametro della funzione
         maxArray = QadVariables.get(QadMsg.translate("Environment variables", "MAXARRAY"))
         if value * self.rectangleRows > maxArray:
            errMsg = QadMsg.translate("Command_ARRAY", "\nThe array size can't be greater than {0} elements. See MAXARRAY system variable.")
            self.showErr(errMsg.format(str(maxArray)))
         else:         
            self.rectangleCols = value
            self.plugIn.setLastRectangleCols_array(self.rectangleCols)
            self.updatePointMapToolParams()
            self.waitForRectangleDistanceBetweenCols(True) # con opzione "TOTAL"
         return False
      
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DELLA DISTANZA TRA COLONNE (da step = ASK_FOR_COLUMN_N)
      elif self.step == QadARRAYCommandClassStepEnum.ASK_FOR_COLUMN_SPACE_OR_TOT: # 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
                  value = self.defaultValue 
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False
            else:
               value = self.getPointMapTool().point
         else: # il punto arriva come parametro della funzione
            value = msg

         if type(value) == QgsPoint: # se é stato inserito il primo punto per misurare la distanza tra righe
            self.waitForRectangleColumnsSpacing2Pt(value)
         elif type(value) == float: # se é stato inserita la distanza
            self.distanceBetweenCols = value
            self.waitForMainOptions()
         elif type(value) == unicode:
            if value == QadMsg.translate("Command_ARRAY", "Total") or value == "Total":
               self.waitForRectangleTotalDistanceCols()
         return False # fine comando


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL SECONDO PT PER MISURARE LA DISTANZA TOTALE TRA COLONNE (da step = ASK_FOR_COLUMN_SPACE_OR_TOT)
      elif self.step == QadARRAYCommandClassStepEnum.ASK_FOR_COLUMN_SPACE_TOT: # dopo aver atteso un punto si riavvia il comando
         if self.GetDistClass.run(msgMapTool, msg) == True:
            if self.GetDistClass.dist is not None:
               if self.rectangleCols > 1:
                  self.distanceBetweenCols = self.GetDistClass.dist / (self.rectangleCols - 1)
               
            del self.GetDistClass
            self.GetDistClass = None
            self.waitForMainOptions()
         return False # fine comando


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL NUMERO DELLE RIGHE OPZIONE ROW (da step = ASK_FOR_MAIN_OPTIONS)
      #=========================================================================
      elif self.step == QadARRAYCommandClassStepEnum.ASK_FOR_ROW_N: # dopo aver atteso un numero intero si riavvia il comando
         if msgMapTool == True: # il punto arriva da una selezione grafica
            if self.getPointMapTool().rightButton == True: # se usato il tasto destro del mouse
               value = self.defaultValue 
            else:
               self.setMapTool(self.getPointMapTool()) # riattivo il maptool
               return False
         else:
            # il numero di righe arriva come parametro della funzione
            value = msg

         maxArray = QadVariables.get(QadMsg.translate("Environment variables", "MAXARRAY"))
         # il numero di righe arriva come parametro della funzione
         if self.arrayType == QadARRAYCommandClassSeriesTypeEnum.RECTANGLE:
            if value * self.rectangleCols > maxArray:
               errMsg = QadMsg.translate("Command_ARRAY", "\nThe array size can't be greater than {0} elements. See MAXARRAY system variable.")
               self.showErr(errMsg.format(str(maxArray)))
               return False
            else:
               self.rectangleRows = value
               self.plugIn.setLastRectangleRows_array(self.rectangleRows)
         elif self.arrayType == QadARRAYCommandClassSeriesTypeEnum.PATH:
            if value * self.pathItemsNumber > maxArray:
               errMsg = QadMsg.translate("Command_ARRAY", "\nThe array size can't be greater than {0} elements. See MAXARRAY system variable.")
               self.showErr(errMsg.format(str(maxArray)))
               return False
            else:
               self.pathRows = value
               self.plugIn.setLastPathRows_array(self.pathRows)
         elif self.arrayType == QadARRAYCommandClassSeriesTypeEnum.POLAR:
            if value * self.polarItemsNumber > maxArray:
               errMsg = QadMsg.translate("Command_ARRAY", "\nThe array size can't be greater than {0} elements. See MAXARRAY system variable.")
               self.showErr(errMsg.format(str(maxArray)))
               return False
            else:
               self.polarRows = value
               self.plugIn.setLastPolarRows_array(self.polarRows)
         
         self.updatePointMapToolParams()
         self.waitForDistanceBetweenRows(True, QadARRAYCommandClassStepEnum.ASK_FOR_ROW_SPACE_OR_TOT) # con opzione "TOTAL"
         return False
      
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DELLA DISTANZA TRA RIGHE (da step = ASK_FOR_ROW_N)
      elif self.step == QadARRAYCommandClassStepEnum.ASK_FOR_ROW_SPACE_OR_TOT: # 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
                  value = self.defaultValue 
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False
            else:
               value = self.getPointMapTool().point
         else: # il punto arriva come parametro della funzione
            value = msg

         if type(value) == QgsPoint: # se é stato inserito il primo punto per misurare la distanza tra righe
            self.waitForDistanceBetweenRows2Pt(value)
         elif type(value) == float: # se é stato inserita la distanza
            self.distanceBetweenRows = value
            self.waitForMainOptions()
         elif type(value) == unicode:
            if value == QadMsg.translate("Command_ARRAY", "Total") or value == "Total":
               self.waitForTotalDistanceRows()
         return False # fine comando


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL SECONDO PT PER MISURARE LA DISTANZA TOTALE TRA RIGHE (da step = ASK_FOR_ROW_SPACE)
      elif self.step == QadARRAYCommandClassStepEnum.ASK_FOR_ROW_SPACE_TOT: # dopo aver atteso un punto si riavvia il comando
         if self.GetDistClass.run(msgMapTool, msg) == True:
            if self.GetDistClass.dist is not None:
               if self.arrayType == QadARRAYCommandClassSeriesTypeEnum.RECTANGLE:
                  if self.rectangleRows > 1:
                     self.distanceBetweenRows = self.GetDistClass.dist / (self.rectangleRows - 1)
               elif self.arrayType == QadARRAYCommandClassSeriesTypeEnum.PATH:
                  if self.pathRows > 1:
                     self.distanceBetweenRows = self.GetDistClass.dist / (self.pathRows - 1)
               elif self.arrayType == QadARRAYCommandClassSeriesTypeEnum.POLAR:
                  if self.polarRows > 1:
                     self.distanceBetweenRows = self.GetDistClass.dist / (self.polarRows - 1)

            del self.GetDistClass
            self.GetDistClass = None
            self.waitForMainOptions()
         return False


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL NUMERO DI ELEMENTI DELLA SERIE (da step = ASK_FOR_MAIN_OPTIONS)
      elif self.step == QadARRAYCommandClassStepEnum.ASK_FOR_ITEM_N:
         if msgMapTool == True: # il punto arriva da una selezione grafica
            if self.getPointMapTool().rightButton == True: # se usato il tasto destro del mouse
               value = self.defaultValue 
            else:
               self.setMapTool(self.getPointMapTool()) # riattivo il maptool
               return False
         else:
            # il numero di elementi arriva come parametro della funzione
            value = msg

         maxArray = QadVariables.get(QadMsg.translate("Environment variables", "MAXARRAY"))

         if self.arrayType == QadARRAYCommandClassSeriesTypeEnum.PATH:
            if self.pathMethod == QadARRAYCommandClassPathMethodTypeEnum.DIVIDE:
               if type(value) == int or type(value) == long: # se é stato inserito il numero di elementi
                  if value * self.pathRows > maxArray:
                     errMsg = QadMsg.translate("Command_ARRAY", "\nThe array size can't be greater than {0} elements. See MAXARRAY system variable.")
                     self.showErr(errMsg.format(str(maxArray)))
                  else:
                     self.pathItemsNumber = value
                     self.setDistancesByPathItemNumberOnDivide()
                     self.waitForMainOptions()
            elif self.pathMethod == QadARRAYCommandClassPathMethodTypeEnum.MEASURE:
               if type(value) == int or type(value) == long: # se é stato inserito il numero di elementi
                  if value * self.pathRows > maxArray:
                     errMsg = QadMsg.translate("Command_ARRAY", "\nThe array size can't be greater than {0} elements. See MAXARRAY system variable.")
                     self.showErr(errMsg.format(str(maxArray)))
                  elif (value - 1) * self.distanceBetweenCols > self.pathLinearObjectList.length():
                     errMsg = QadMsg.translate("Command_ARRAY", "\nMaximun number of items = {0}.")
                     self.showErr(errMsg.format(str(int(self.pathLinearObjectList.length() / self.distanceBetweenCols) + 1)))
                  else:
                     self.pathItemsNumber = value
                     self.distanceFromStartPt = 0.0
                     self.waitForMainOptions()
               elif type(value) == unicode:
                  if value == QadMsg.translate("Command_ARRAY", "Fill entire path") or value == "Fill entire path":
                     self.setItemNumberByDistanceBetweenColsOnMeasure()
                     self.waitForMainOptions()
         elif self.arrayType == QadARRAYCommandClassSeriesTypeEnum.POLAR:
            if msg * self.polarRows > maxArray:
               errMsg = QadMsg.translate("Command_ARRAY", "\nThe array size can't be greater than {0} elements. See MAXARRAY system variable.")
               self.showErr(errMsg.format(str(maxArray)))
            else:
               fillAngle = self.polarItemsNumber * self.polarAngleBetween
               self.polarItemsNumber = value
               self.polarAngleBetween = 2 * math.pi / value
               self.plugIn.setLastPolarItemsNumber_array(self.polarItemsNumber)
               self.plugIn.setLastPolarAngleBetween_array(self.polarAngleBetween)
               self.waitForMainOptions()
               
         return False # fine comando


   #============================================================================
   # SERIE TRAIETTORIA  - INIZIO
   #============================================================================


      #=========================================================================
      # RISPOSTA ALLA SELEZIONE DI UN'ENTITA' DA USARE COME PERCORSO DELLA SERIE (da step = ASK_FOR_ARRAYTYPE)
      elif self.step == QadARRAYCommandClassStepEnum.ASK_FOR_PATH_OBJ:
         if self.entSelClass.run(msgMapTool, msg) == True:
            if self.entSelClass.entity.isInitialized():
               if self.setPathLinearObjectList(self.entSelClass.entity, self.entSelClass.point) == True:
                  self.setItemNumberByDistanceBetweenColsOnMeasure()
                  self.waitForMainOptions()
            else:               
               if self.entSelClass.canceledByUsr == True: # fine comando
                  return True
               self.showMsg(QadMsg.translate("QAD", "No geometries in this position."))
               self.waitForPathObject(msgMapTool, msg)
               
         return False


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL METODO (da step = ASK_FOR_MAIN_OPTIONS)
      elif self.step == QadARRAYCommandClassStepEnum.ASK_FOR_PATH_METHOD: # dopo aver atteso una parola chiave si riavvia il comando
         if msgMapTool == True: # il punto arriva da una selezione grafica
            if self.getPointMapTool().rightButton == True: # se usato il tasto destro del mouse
               value = self.defaultValue 
            else:
               self.setMapTool(self.getPointMapTool()) # riattivo il maptool
               return False
         else:
            # la parola chiave arriva come parametro della funzione
            value = msg

         if type(value) == unicode:
            if value == QadMsg.translate("Command_ARRAY", "Divide") or value == "Divide":
               self.pathMethod = QadARRAYCommandClassPathMethodTypeEnum.DIVIDE
               self.setDistancesByPathItemNumberOnDivide()
            elif value == QadMsg.translate("Command_ARRAY", "Measure") or value == "Measure":
               self.pathMethod = QadARRAYCommandClassPathMethodTypeEnum.MEASURE
               self.setItemNumberByDistanceBetweenColsOnMeasure()
            self.waitForMainOptions()
         
         return False 


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DELLA DIREZIONE DELLA TANGENTE (da step = ASK_FOR_MAIN_OPTIONS)
      #=========================================================================
      elif self.step == QadARRAYCommandClassStepEnum.ASK_FOR_TAN_DIRECTION:
         if self.GetAngleClass.run(msgMapTool, msg) == True:
            if self.GetAngleClass.angle is not None:
               self.pathTangentDirection = self.GetAngleClass.angle
               self.plugIn.setLastPathTangentDirection_array(self.pathTangentDirection)
            self.waitForMainOptions()
            
         return False


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL SECONDO PT PER MISURARE LA DISTANZA TRA ELEMENTI (da step = ASK_FOR_MAIN_OPTIONS)
      elif self.step == QadARRAYCommandClassStepEnum.ASK_FOR_ITEM_SPACE: 
         if self.GetDistClass.run(msgMapTool, msg) == True:
            if self.GetDistClass.dist is not None:
               l = self.pathLinearObjectList.length()
               if self.GetDistClass.dist > l:
                  errMsg = QadMsg.translate("Command_ARRAY", "\nThe distance between items can't be greater than {0}.")
                  self.showErr(errMsg.format(str(l)))
               else:
                  self.distanceBetweenCols = self.GetDistClass.dist

            del self.GetDistClass
            self.GetDistClass = None
            self.updatePointMapToolParams()
            self.waitForItemsNumber()
         return False # fine comando


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DELL'ALLINEAMENTO DEGLI ELEMENTI (da step = ASK_FOR_MAIN_OPTIONS)
      elif self.step == QadARRAYCommandClassStepEnum.ASK_FOR_ITEM_ROTATION: # dopo aver atteso una parola chiave si riavvia il comando
         if msgMapTool == True: # il punto arriva da una selezione grafica
            if self.getPointMapTool().rightButton == True: # se usato il tasto destro del mouse
               value = self.defaultValue 
            else:
               self.setMapTool(self.getPointMapTool()) # riattivo il maptool
               return False
         else:
            # la parola chiave arriva come parametro della funzione
            value = msg

         if type(value) == unicode:
            if value == QadMsg.translate("QAD", "Yes") or value == "Yes":
               self.itemsRotation = True
            elif value == QadMsg.translate("QAD", "No") or value == "No":
               self.itemsRotation = False
            self.plugIn.setLastItemsRotation_array(self.itemsRotation)
            self.waitForMainOptions()
         
         return False 


   #============================================================================
   # SERIE TRAIETTORIA  - FINE
   # SERIE POLARE       - INIZIO
   #============================================================================


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL CENTRO DELLA SERIE ((da step = ASK_FOR_ARRAYTYPE))
      elif self.step == QadARRAYCommandClassStepEnum.ASK_FOR_CENTER_PT: # 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
                  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: # se é stato inserito il punto centrale della serie
            self.centerPt.set(value.x(), value.y())
            self.waitForMainOptions()
         elif type(value) == unicode:
            if value == QadMsg.translate("Command_ARRAY", "Base point") or value == "Base point":
               self.updatePointMapToolParams()
               self.waitForBasePt(QadARRAYCommandClassStepEnum.ASK_FOR_BASE_PT_BEFORE_MAIN_OPTIONS)
         return False # fine comando
         
         
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL PUNTO BASE (da step = ASK_FOR_CENTER_PT)
      elif self.step == QadARRAYCommandClassStepEnum.ASK_FOR_BASE_PT_BEFORE_MAIN_OPTIONS: # 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
                  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.set(value.x(), value.y())
         self.updatePointMapToolParams()
         self.waitForPolarCenterPt()
         return False


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DELL'ANGOLO TRA GLI ELEMENTI (da step = ASK_FOR_MAIN_OPTIONS)
      #=========================================================================
      elif self.step == QadARRAYCommandClassStepEnum.ASK_FOR_ANGLE_BETWEEN_ITEMS:
         if self.GetAngleClass.run(msgMapTool, msg) == True:
            if self.GetAngleClass.angle is not None:
               if self.GetAngleClass.angle * self.polarItemsNumber > math.pi * 2:
                  errMsg = QadMsg.translate("Command_ARRAY", "\nThe angle between can't be greater than {0}.")
                  maxAngleBetween = math.pi * 2 / self.polarItemsNumber
                  self.showErr(errMsg.format(str(qad_utils.toDegrees(maxAngleBetween))))
               else:
                  self.polarAngleBetween = self.GetAngleClass.angle               
                  self.plugIn.setLastPolarAngleBetween_array(self.polarAngleBetween)
                  
            self.waitForMainOptions()
            
         return False


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DELL'ANGOLO TRA GLI ELEMENTI (da step = ASK_FOR_MAIN_OPTIONS)
      #=========================================================================
      elif self.step == QadARRAYCommandClassStepEnum.ASK_FOR_FULL_ANGLE:
         if self.GetAngleClass.run(msgMapTool, msg) == True:
            if self.GetAngleClass.angle is not None:
               self.polarAngleBetween = self.GetAngleClass.angle / self.polarItemsNumber
               self.plugIn.setLastPolarAngleBetween_array(self.polarAngleBetween)               
            self.waitForMainOptions()
            
         return False class QadARRAYRECTCommandClass(QadCommandClass):

   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadARRAYRECTCommandClass(self.plugIn)
   
   def getName(self):
      return QadMsg.translate("Command_list", "ARRAYRECT")

   def getEnglishName(self):
      return "ARRAYRECT"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runARRAYRECTCommand)

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/arrayRect.png")

   def getNote(self):
      # impostare le note esplicative del comando
      return QadMsg.translate("Command_ARRAY", "Distributes object copies into any combination of rows and columns.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      self.SSGetClass = QadSSGetClass(plugIn)
      self.SSGetClass.onlyEditableLayers = True
      self.arrayCmd = QadARRAYCommandClass(plugIn)

   def __del__(self):
      QadCommandClass.__del__(self)
      if self.SSGetClass is not None:
         del self.SSGetClass
      del self.arrayCmd


   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      if self.step == QadARRAYCommandClassStepEnum.ASK_FOR_SELSET: # quando si é in fase di selezione entità
         return self.SSGetClass.getPointMapTool()
      else:
         return self.arrayCmd.getPointMapTool()


   def getCurrentContextualMenu(self):
      if self.step == QadARRAYCommandClassStepEnum.ASK_FOR_SELSET: # quando si é in fase di selezione entità
         return self.SSGetClass.getCurrentContextualMenu()
      else:
         return self.arrayCmd.getCurrentContextualMenu()


   #============================================================================
   # 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 == QadARRAYCommandClassStepEnum.ASK_FOR_SELSET: # inizio del comando
         if self.SSGetClass.run(msgMapTool, msg) == True:
            if self.SSGetClass.entitySet.count() == 0:
               return True # fine comando
            self.arrayCmd.setEntitySet(self.SSGetClass.entitySet)
            
            del self.SSGetClass
            self.SSGetClass = None
            
            self.step = -1
            self.arrayCmd.step = QadARRAYCommandClassStepEnum.ASK_FOR_ARRAYTYPE
            
            return self.arrayCmd.run(False, QadMsg.translate("Command_ARRAY", "Rectangular"))
            
         return False

      else:
         return self.arrayCmd.run(msgMapTool, msg) class QadARRAYPATHCommandClass(QadCommandClass):

   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadARRAYPATHCommandClass(self.plugIn)
   
   def getName(self):
      return QadMsg.translate("Command_list", "ARRAYPATH")

   def getEnglishName(self):
      return "ARRAYPATH"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runARRAYPATHCommand)

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/arrayPath.png")

   def getNote(self):
      # impostare le note esplicative del comando
      return QadMsg.translate("Command_ARRAY", "Evenly distributes object copies along a path or a portion of a path.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      self.SSGetClass = QadSSGetClass(plugIn)
      self.SSGetClass.onlyEditableLayers = True
      self.arrayCmd = QadARRAYCommandClass(plugIn)

   def __del__(self):
      QadCommandClass.__del__(self)
      if self.SSGetClass is not None:
         del self.SSGetClass
      del self.arrayCmd


   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      if self.step == QadARRAYCommandClassStepEnum.ASK_FOR_SELSET: # quando si é in fase di selezione entità
         return self.SSGetClass.getPointMapTool()
      else:
         return self.arrayCmd.getPointMapTool()


   def getCurrentContextualMenu(self):
      if self.step == QadARRAYCommandClassStepEnum.ASK_FOR_SELSET: # quando si é in fase di selezione entità
         return self.SSGetClass.getCurrentContextualMenu()
      else:
         return self.arrayCmd.getCurrentContextualMenu()


   #============================================================================
   # 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 == QadARRAYCommandClassStepEnum.ASK_FOR_SELSET: # inizio del comando
         if self.SSGetClass.run(msgMapTool, msg) == True:
            if self.SSGetClass.entitySet.count() == 0:
               return True # fine comando
            self.arrayCmd.setEntitySet(self.SSGetClass.entitySet)
            
            del self.SSGetClass
            self.SSGetClass = None
            
            self.step = -1
            self.arrayCmd.step = QadARRAYCommandClassStepEnum.ASK_FOR_ARRAYTYPE
            
            return self.arrayCmd.run(False, QadMsg.translate("Command_ARRAY", "PAth"))
            
         return False

      else:
         return self.arrayCmd.run(msgMapTool, msg) class QadARRAYPOLARCommandClass(QadCommandClass):

   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadARRAYPOLARCommandClass(self.plugIn)
   
   def getName(self):
      return QadMsg.translate("Command_list", "ARRAYPOLAR")

   def getEnglishName(self):
      return "ARRAYPOLAR"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runARRAYPOLARCommand)

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/arrayPolar.png")

   def getNote(self):
      # impostare le note esplicative del comando
      return QadMsg.translate("Command_ARRAY", "Evenly distributes object copies in a circular pattern around a center point.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      self.SSGetClass = QadSSGetClass(plugIn)
      self.SSGetClass.onlyEditableLayers = True
      self.arrayCmd = QadARRAYCommandClass(plugIn)

   def __del__(self):
      QadCommandClass.__del__(self)
      if self.SSGetClass is not None:
         del self.SSGetClass
      del self.arrayCmd

   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      if self.step == QadARRAYCommandClassStepEnum.ASK_FOR_SELSET: # quando si é in fase di selezione entità
         return self.SSGetClass.getPointMapTool()
      else:
         return self.arrayCmd.getPointMapTool()


   def getCurrentContextualMenu(self):
      if self.step == QadARRAYCommandClassStepEnum.ASK_FOR_SELSET: # quando si é in fase di selezione entità
         return self.SSGetClass.getCurrentContextualMenu()
      else:
         return self.arrayCmd.getCurrentContextualMenu()


   #============================================================================
   # 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 == QadARRAYCommandClassStepEnum.ASK_FOR_SELSET: # inizio del comando
         if self.SSGetClass.run(msgMapTool, msg) == True:
            if self.SSGetClass.entitySet.count() == 0:
               return True # fine comando
            self.arrayCmd.setEntitySet(self.SSGetClass.entitySet)
            
            del self.SSGetClass
            self.SSGetClass = None
            
            self.step = -1
            self.arrayCmd.step = QadARRAYCommandClassStepEnum.ASK_FOR_ARRAYTYPE
            
            return self.arrayCmd.run(False, QadMsg.translate("Command_ARRAY", "POlar"))
            
         return False

      else:
         return self.arrayCmd.run(msgMapTool, msg) class QadDIVIDECommandClass(QadCommandClass):

   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadDIVIDECommandClass(self.plugIn)
   
   def getName(self):
      return QadMsg.translate("Command_list", "DIVIDE")

   def getEnglishName(self):
      return "DIVIDE"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runDIVIDECommand)

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/divide.png")

   def getNote(self):
      # impostare le note esplicative del comando
      return QadMsg.translate("Command_DIVIDE", "Creates evenly spaced punctual objects along the length or perimeter of an object.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      self.entSelClass = None
      self.objectAlignment = True
      self.nSegments = 1

   def __del__(self):
      QadCommandClass.__del__(self)
      if self.entSelClass is not None:
         self.entSelClass.entity.deselectOnLayer()
         del self.entSelClass
      

   #============================================================================
   # waitForEntsel
   #============================================================================
   def waitForEntsel(self, msgMapTool, msg):
      if self.entSelClass is not None:
         del self.entSelClass
      self.step = QadDIVIDECommandClassStepEnum.ASK_FOR_ENT
      self.entSelClass = QadEntSelClass(self.plugIn)
      self.entSelClass.msg = QadMsg.translate("Command_DIVIDE", "Select object to divide: ")
      # scarto la selezione di punti
      self.entSelClass.checkPointLayer = False
      self.entSelClass.checkLineLayer = True
      self.entSelClass.checkPolygonLayer = True
      self.entSelClass.checkDimLayers = False
      self.entSelClass.onlyEditableLayers = False

      self.entSelClass.run(msgMapTool, msg)


   #============================================================================
   # waitForAlignmentObjs
   #============================================================================
   def waitForAlignmentObjs(self):
      self.step = QadDIVIDECommandClassStepEnum.ASK_FOR_ALIGNMENT

      keyWords = QadMsg.translate("QAD", "Yes") + "/" + QadMsg.translate("QAD", "No")
      self.defaultValue = QadMsg.translate("QAD", "Yes")
      prompt = QadMsg.translate("Command_DIVIDE", "Align with object ? [{0}] <{1}>: ").format(keyWords, self.defaultValue)
      
      englishKeyWords = "Yes" + "/" + "No"
      keyWords += "_" + englishKeyWords

      # msg, inputType, default, keyWords, nessun controllo
      self.waitFor(prompt, \
                   QadInputTypeEnum.KEYWORDS, \
                   self.defaultValue, \
                   keyWords, QadInputModeEnum.NONE)

   
   #============================================================================
   # waitForSegmentNumber
   #============================================================================
   def waitForSegmentNumber(self):
      self.step = QadDIVIDECommandClassStepEnum.ASK_SEGMENT_NUMBER

      # si appresta ad attendere un numero intero
      msg = QadMsg.translate("Command_DIVIDE", "Enter the number of segments: ")
      # msg, inputType, default, keyWords, valori positivi
      self.waitFor(msg, \
                   QadInputTypeEnum.INT, \
                   None, \
                   "", \
                   QadInputModeEnum.NOT_ZERO | QadInputModeEnum.NOT_NEGATIVE)


   #============================================================================
   # addFeature
   #============================================================================
   def addFeature(self, layer, insPt, rot):
      transformedPoint = self.mapToLayerCoordinates(layer, insPt)
      g = QgsGeometry.fromPoint(transformedPoint)
      f = QgsFeature()
      f.setGeometry(g)
      # Add attribute fields to feature.
      fields = layer.pendingFields()
      f.setFields(fields)
      
      # assegno i valori di default
      provider = layer.dataProvider()
      for field in fields.toList():
         i = fields.indexFromName(field.name())
         f[field.name()] = provider.defaultValue(i)
      
      # se la scala dipende da un campo 
      scaleFldName = qad_layer.get_symbolScaleFieldName(layer)
      if len(scaleFldName) > 0:
         f.setAttribute(scaleFldName, 1.0)
      
      # se la rotazione dipende da un campo
      rotFldName = qad_layer.get_symbolRotationFieldName(layer)
      if len(rotFldName) > 0:
         f.setAttribute(rotFldName, qad_utils.toDegrees(rot))
      
      return qad_layer.addFeatureToLayer(self.plugIn, layer, f)               


   #============================================================================
   # doDivide
   #============================================================================
   def doDivide(self, dstLayer):
      f = self.entSelClass.entity.getFeature()
      if f is None:
         return
      
      layer = self.entSelClass.entity.layer
      
      # trasformo la geometria nel crs del canvas per lavorare con coordinate piane xy
      geom = self.layerToMapCoordinates(layer, f.geometry())
      
      # ritorna una tupla (<The squared cartesian distance>,
      #                    <minDistPoint>
      #                    <afterVertex>
      #                    <leftOf>)
      dummy = qad_utils.closestSegmentWithContext(self.entSelClass.point, geom)
      if dummy[2] is None:
         return False
      
      # ritorna la sotto-geometria al vertice <atVertex> e la sua posizione nella geometria (0-based)
      subGeom, atSubGeom = qad_utils.getSubGeomAtVertex(geom, dummy[2])
      pathLinearObjectList = qad_utils.QadLinearObjectList()
      geomType = subGeom.type()
      pathLinearObjectList.fromPolyline(subGeom.asPolyline())
      distance = pathLinearObjectList.length() / self.nSegments
      
      self.plugIn.beginEditCommand("Feature divided", dstLayer)
      
      i = 1
      distanceFromStart = distance
      while i < self.nSegments:
         pt, rot = pathLinearObjectList.getPointFromStart(distanceFromStart)
         if self.addFeature(dstLayer, pt, rot if self.objectAlignment else 0) == False:
            self.plugIn.destroyEditCommand()
            return False
         i = i + 1
         distanceFromStart = distanceFromStart + distance 

      self.plugIn.endEditCommand()
      return True

   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
      
      currLayer, errMsg = qad_layer.getCurrLayerEditable(self.plugIn.canvas, QGis.Point)
      if currLayer is None:
         self.showErr(errMsg)
         return True # fine comando

      if qad_layer.isSymbolLayer(currLayer) == False :
         errMsg = QadMsg.translate("QAD", "\nCurrent layer is not a symbol layer.")
         errMsg = errMsg + QadMsg.translate("QAD", "\nA symbol layer is a vector punctual layer without label.\n")
         self.showErr(errMsg)
         return True # fine comando
      
      if  len(QadDimStyles.getDimListByLayer(currLayer)) > 0:
         errMsg = QadMsg.translate("QAD", "\nThe current layer belongs to a dimension style.\n")
         self.showErr(errMsg)
         return True # fine comando

      if self.step == 0:     
         self.waitForEntsel(msgMapTool, msg)
         return False # continua


      #=========================================================================
      # RISPOSTA ALLA SELEZIONE DI UN'ENTITA' (da step = 0)
      elif self.step == QadDIVIDECommandClassStepEnum.ASK_FOR_ENT:
         if self.entSelClass.run(msgMapTool, msg) == True:
            if self.entSelClass.entity.isInitialized():
               # se il layer di destinazione è di tipo simbolo
               if qad_layer.isSymbolLayer(currLayer) == True:
                  # se il simbolo può essere ruotato
                  if len(qad_layer.get_symbolRotationFieldName(currLayer)) >0:
                     self.waitForAlignmentObjs()
                  else:
                     self.waitForSegmentNumber()
               return False
            else:
               if self.entSelClass.canceledByUsr == True: # fine comando
                  return True
               self.showMsg(QadMsg.translate("QAD", "No geometries in this position."))
               self.waitForEntsel(msgMapTool, msg)
         return False # continua
      

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DI ALLINEARE GLI OGGETTI (da step = ASK_FOR_ENT)
      elif self.step == QadDIVIDECommandClassStepEnum.ASK_FOR_ALIGNMENT: # dopo aver atteso una parola chiave si riavvia il comando
         if msgMapTool == True: # il punto arriva da una selezione grafica
            if self.getPointMapTool().rightButton == True: # se usato il tasto destro del mouse
               value = self.defaultValue 
            else:
               self.setMapTool(self.getPointMapTool()) # riattivo il maptool
               return False
         else:
            # la parola chiave arriva come parametro della funzione
            value = msg

         if type(value) == unicode:
            if value == QadMsg.translate("QAD", "Yes") or value == "Yes":
               self.objectAlignment = True
            else:
               self.objectAlignment = False

            self.waitForSegmentNumber()
         
         return False 


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL NUMERO DI SEGMENTI (da step = ASK_FOR_ALIGNMENT)
      #=========================================================================
      elif self.step == QadDIVIDECommandClassStepEnum.ASK_SEGMENT_NUMBER: # dopo aver atteso un numero intero si riavvia il comando
         if msgMapTool == True: # il punto arriva da una selezione grafica
            if self.getPointMapTool().rightButton == True: # se usato il tasto destro del mouse
               return False
            else:
               self.setMapTool(self.getPointMapTool()) # riattivo il maptool
               return False
         else:
            # il numero di segmenti arriva come parametro della funzione
            self.nSegments = msg
            self.doDivide(currLayer)
            return True # fine comando
         return False class QadMEASURECommandClass(QadCommandClass):

   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadMEASURECommandClass(self.plugIn)
   
   def getName(self):
      return QadMsg.translate("Command_list", "MEASURE")

   def getEnglishName(self):
      return "MEASURE"

   def connectQAction(self, action):
      QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runMEASURECommand)

   def getIcon(self):
      return QIcon(":/plugins/qad/icons/measure.png")

   def getNote(self):
      # impostare le note esplicative del comando
      return QadMsg.translate("Command_MEASURE", "Creates punctual objects at measured intervals along the length or perimeter of an object.")
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      self.entSelClass = None
      self.GetDistClass = None
      self.objectAlignment = True
      self.segmentLength = 1

   def __del__(self):
      QadCommandClass.__del__(self)
      if self.entSelClass is not None:
         self.entSelClass.entity.deselectOnLayer()
         del self.entSelClass


   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      if self.step == QadMEASURECommandClassStepEnum.ASK_SEGMENT_LENGTH: # quando si é in fase di richiesta distanza
         return self.GetDistClass.getPointMapTool()
      else:
         return QadCommandClass.getPointMapTool(self, drawMode)
      

   def getCurrentContextualMenu(self):
      if self.step == QadMEASURECommandClassStepEnum.ASK_SEGMENT_LENGTH: # quando si é in fase di richiesta distanza
         return self.GetDistClass.getCurrentContextualMenu()
      else:
         return self.contextualMenu


   #============================================================================
   # waitForEntsel
   #============================================================================
   def waitForEntsel(self, msgMapTool, msg):
      if self.entSelClass is not None:
         del self.entSelClass
      self.step = QadMEASURECommandClassStepEnum.ASK_FOR_ENT
      self.entSelClass = QadEntSelClass(self.plugIn)
      self.entSelClass.msg = QadMsg.translate("Command_MEASURE", "Select object to measure: ")
      # scarto la selezione di punti
      self.entSelClass.checkPointLayer = False
      self.entSelClass.checkLineLayer = True
      self.entSelClass.checkPolygonLayer = True
      self.entSelClass.checkDimLayers = False
      self.entSelClass.onlyEditableLayers = False

      self.entSelClass.run(msgMapTool, msg)


   #============================================================================
   # waitForAlignmentObjs
   #============================================================================
   def waitForAlignmentObjs(self):
      self.step = QadMEASURECommandClassStepEnum.ASK_FOR_ALIGNMENT

      keyWords = QadMsg.translate("QAD", "Yes") + "/" + QadMsg.translate("QAD", "No")
      self.defaultValue = QadMsg.translate("QAD", "Yes")
      prompt = QadMsg.translate("Command_MEASURE", "Align with object ? [{0}] <{1}>: ").format(keyWords, self.defaultValue)
      
      englishKeyWords = "Yes" + "/" + "No"
      keyWords += "_" + englishKeyWords

      # msg, inputType, default, keyWords, nessun controllo
      self.waitFor(prompt, \
                   QadInputTypeEnum.KEYWORDS, \
                   self.defaultValue, \
                   keyWords, QadInputModeEnum.NONE)

   
   #============================================================================
   # waitForSegmentLength
   #============================================================================
   def waitForSegmentLength(self):
      self.step = QadMEASURECommandClassStepEnum.ASK_SEGMENT_LENGTH
      
      if self.GetDistClass is not None:
         del self.GetDistClass
      self.GetDistClass = QadGetDistClass(self.plugIn)
      
      self.GetDistClass.msg = QadMsg.translate("Command_MEASURE", "Enter the length of segment: ")
      self.GetDistClass.run()


   #============================================================================
   # addFeature
   #============================================================================
   def addFeature(self, layer, insPt, rot):
      transformedPoint = self.mapToLayerCoordinates(layer, insPt)
      g = QgsGeometry.fromPoint(transformedPoint)
      f = QgsFeature()
      f.setGeometry(g)
      # Add attribute fields to feature.
      fields = layer.pendingFields()
      f.setFields(fields)
      
      # assegno i valori di default
      provider = layer.dataProvider()
      for field in fields.toList():
         i = fields.indexFromName(field.name())
         f[field.name()] = provider.defaultValue(i)
      
      # se la scala dipende da un campo 
      scaleFldName = qad_layer.get_symbolScaleFieldName(layer)
      if len(scaleFldName) > 0:
         f.setAttribute(scaleFldName, 1.0)
      
      # se la rotazione dipende da un campo
      rotFldName = qad_layer.get_symbolRotationFieldName(layer)
      if len(rotFldName) > 0:
         f.setAttribute(rotFldName, qad_utils.toDegrees(rot))
      
      return qad_layer.addFeatureToLayer(self.plugIn, layer, f)               


   #============================================================================
   # doMeasure
   #============================================================================
   def doMeasure(self, dstLayer):
      f = self.entSelClass.entity.getFeature()
      if f is None:
         return
      
      layer = self.entSelClass.entity.layer
      
      # trasformo la geometria nel crs del canvas per lavorare con coordinate piane xy
      geom = self.layerToMapCoordinates(layer, f.geometry())
      
      # ritorna una tupla (<The squared cartesian distance>,
      #                    <minDistPoint>
      #                    <afterVertex>
      #                    <leftOf>)
      dummy = qad_utils.closestSegmentWithContext(self.entSelClass.point, geom)
      if dummy[2] is None:
         return False
      
      # ritorna la sotto-geometria al vertice <atVertex> e la sua posizione nella geometria (0-based)
      subGeom, atSubGeom = qad_utils.getSubGeomAtVertex(geom, dummy[2])
      pathLinearObjectList = qad_utils.QadLinearObjectList()
      geomType = subGeom.type()
      pathLinearObjectList.fromPolyline(subGeom.asPolyline())
      length = pathLinearObjectList.length()
      
      self.plugIn.beginEditCommand("Feature measured", dstLayer)
      
      i = 1
      distanceFromStart = self.segmentLength
      while distanceFromStart <= length:
         pt, rot = pathLinearObjectList.getPointFromStart(distanceFromStart)
         if self.addFeature(dstLayer, pt, rot if self.objectAlignment else 0) == False:
            self.plugIn.destroyEditCommand()
            return False
         i = i + 1
         distanceFromStart = distanceFromStart + self.segmentLength 

      self.plugIn.endEditCommand()
      return True

   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
      
      currLayer, errMsg = qad_layer.getCurrLayerEditable(self.plugIn.canvas, QGis.Point)
      if currLayer is None:
         self.showErr(errMsg)
         return True # fine comando

      if qad_layer.isSymbolLayer(currLayer) == False :
         errMsg = QadMsg.translate("QAD", "\nCurrent layer is not a symbol layer.")
         errMsg = errMsg + QadMsg.translate("QAD", "\nA symbol layer is a vector punctual layer without label.\n")
         self.showErr(errMsg)
         return True # fine comando
      
      if  len(QadDimStyles.getDimListByLayer(currLayer)) > 0:
         errMsg = QadMsg.translate("QAD", "\nThe current layer belongs to a dimension style.\n")
         self.showErr(errMsg)
         return True # fine comando

      if self.step == 0:     
         self.waitForEntsel(msgMapTool, msg)
         return False # continua


      #=========================================================================
      # RISPOSTA ALLA SELEZIONE DI UN'ENTITA' (da step = 0)
      elif self.step == QadMEASURECommandClassStepEnum.ASK_FOR_ENT:
         if self.entSelClass.run(msgMapTool, msg) == True:
            if self.entSelClass.entity.isInitialized():
               # se il layer di destinazione è di tipo simbolo
               if qad_layer.isSymbolLayer(currLayer) == True:
                  # se il simbolo può essere ruotato
                  if len(qad_layer.get_symbolRotationFieldName(currLayer)) >0:
                     self.waitForAlignmentObjs()
                  else:
                     self.waitForSegmentLength()
               return False
            else:
               if self.entSelClass.canceledByUsr == True: # fine comando
                  return True
               self.showMsg(QadMsg.translate("QAD", "No geometries in this position."))
               self.waitForEntsel(msgMapTool, msg)
         return False # continua
      

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DI ALLINEARE GLI OGGETTI (da step = ASK_FOR_ENT)
      elif self.step == QadMEASURECommandClassStepEnum.ASK_FOR_ALIGNMENT: # dopo aver atteso una parola chiave si riavvia il comando
         if msgMapTool == True: # il punto arriva da una selezione grafica
            if self.getPointMapTool().rightButton == True: # se usato il tasto destro del mouse
               value = self.defaultValue 
            else:
               self.setMapTool(self.getPointMapTool()) # riattivo il maptool
               return False
         else:
            # la parola chiave arriva come parametro della funzione
            value = msg

         if type(value) == unicode:
            if value == QadMsg.translate("QAD", "Yes") or value == "Yes":
               self.objectAlignment = True
            else:
               self.objectAlignment = False

            self.waitForSegmentLength()
         
         return False 


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DELLA LUNGHEZZA DEL SEGMENTO (da step = ASK_FOR_ALIGNMENT)
      #=========================================================================
      elif self.step == QadMEASURECommandClassStepEnum.ASK_SEGMENT_LENGTH: # dopo aver atteso un numero reale si riavvia il comando
         if self.GetDistClass.run(msgMapTool, msg) == True:
            self.getPointMapTool().refreshSnapType() # aggiorno lo snapType che può essere variato da altri maptool
            if self.GetDistClass.dist is not None:
               self.segmentLength = self.GetDistClass.dist
               self.doMeasure(currLayer)

            del self.GetDistClass
            return True # fine comando
         else:
            return False
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from qgis.core import *
from qgis.gui import *
from qad_maptool import QadMapTool, QadVirtualSelCommandClass, QadVirtualGripCommandsClass
from qad_msg import QadMsg
from qad_cmd_aliases import *
from qad_variables import QadVariables
from qad_getpoint import *
from qad_generic_cmd import QadCommandClass
from qad_id_cmd import QadIDCommandClass
from qad_setcurrlayerbygraph_cmd import QadSETCURRLAYERBYGRAPHCommandClass, QadSETCURRUPDATEABLELAYERBYGRAPHCommandClass
from qad_setvar_cmd import QadSETVARCommandClass
from qad_pline_cmd import QadPLINECommandClass
from qad_arc_cmd import QadARCCommandClass
from qad_circle_cmd import QadCIRCLECommandClass
from qad_dsettings_cmd import QadDSETTINGSCommandClass
from qad_line_cmd import QadLINECommandClass
from qad_erase_cmd import QadERASECommandClass
from qad_mpolygon_cmd import QadMPOLYGONCommandClass
from qad_mbuffer_cmd import QadMBUFFERCommandClass
from qad_rotate_cmd import QadROTATECommandClass
from qad_move_cmd import QadMOVECommandClass
from qad_scale_cmd import QadSCALECommandClass
from qad_copy_cmd import QadCOPYCommandClass
from qad_offset_cmd import QadOFFSETCommandClass
from qad_extend_cmd import QadEXTENDCommandClass
from qad_trim_cmd import QadTRIMCommandClass
from qad_rectangle_cmd import QadRECTANGLECommandClass
from qad_mirror_cmd import QadMIRRORCommandClass
from qad_undoredo_cmd import QadUNDOCommandClass, QadREDOCommandClass
from qad_insert_cmd import QadINSERTCommandClass
from qad_text_cmd import QadTEXTCommandClass
from qad_stretch_cmd import QadSTRETCHCommandClass
from qad_break_cmd import QadBREAKCommandClass
from qad_pedit_cmd import QadPEDITCommandClass
from qad_fillet_cmd import QadFILLETCommandClass
from qad_polygon_cmd import QadPOLYGONCommandClass
from qad_dim_cmd import QadDIMLINEARCommandClass, QadDIMALIGNEDCommandClass, QadDIMARCCommandClass
from qad_dimstyle_cmd import QadDIMSTYLECommandClass
from qad_lengthen_cmd import QadLENGTHENCommandClass
from qad_help_cmd import QadHELPCommandClass
from qad_options_cmd import QadOPTIONSCommandClass
from qad_mapmpedit_cmd import QadMAPMPEDITCommandClass
from qad_joindisjoin_cmd import QadJOINCommandClass, QadDISJOINCommandClass
from qad_array_cmd import QadARRAYCommandClass, QadARRAYRECTCommandClass, QadARRAYPATHCommandClass, QadARRAYPOLARCommandClass
from qad_divide_cmd import QadDIVIDECommandClass
from qad_measure_cmd import QadMEASURECommandClass
import sys, traceback
# -*- coding: utf-8 -*-

"""
/***************************************************************************
 QAD Quantum Aided Design plugin

 classe per gestire i comandi
 
                              -------------------
        begin                : 2013-05-22
        copyright            : iiiii
        email                : hhhhh
        developers           : bbbbb aaaaa ggggg
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
"""


# Import the PyQt and QGIS libraries





# Classe che gestisce i comandi di Qad
class QadCommandsClass():
   # quando si aggiunge un nuovo comando bisogna
   # 1) aggiungerlo nella lista __cmdObjs nella funzione __init__ 
   # 2) se il comando può essere richiamato da menu o da toolbar vedere la funzione Qad::initGui (qad.py)
   #    e ricordarsi di inserire l'icona in resources.qrc e di ricompilare le risorse
   # 3) aggiungere funzione per l'avvio del comando "run<nome_comando>Command"
   
   def __init__(self, plugIn):   
      self.plugIn = plugIn
      
      self.__cmdObjs = [] # lista interna degli oggetti comandi
      self.__cmdObjs.append(QadIDCommandClass(self.plugIn)) # ID
      self.__cmdObjs.append(QadSETVARCommandClass(self.plugIn)) # SETVAR
      self.__cmdObjs.append(QadPLINECommandClass(self.plugIn)) # PLINE

      self.__cmdObjs.append(QadSETCURRLAYERBYGRAPHCommandClass(self.plugIn))# SETCURRLAYERBYGRAPH