def __init__(self, iface):
		QtGui.QDialog.__init__(self)
		# Set up the user interface from Designer.
		self.iface = iface
		self.canvas = iface.mapCanvas()
		self.ui = Ui_VectorGeoref()
		self.ui.setupUi(self)
		self.customize_GUI()
		# connect the layer changed handler to a signal that the TOC layer has changed
		QObject.connect(self.iface,SIGNAL("currentLayerChanged(QgsMapLayer *)"), self.myHandleLayerChange)
		# inizializza i dati sul layer
		self.myHandleLayerChange()
		self.newProj()
class VectorGeorefDialog(QtGui.QDialog, Matrix_functions):
	vLayer = ""
	mapPreview = ""
	markerList1 = []	# lista dei marcatori del canvas1
	markerList2 = []	# lista dei marcatori del canvas2
	anTxtList = []		# lista delle annotazioni

	def __init__(self, iface):
		QtGui.QDialog.__init__(self)
		# Set up the user interface from Designer.
		self.iface = iface
		self.canvas = iface.mapCanvas()
		self.ui = Ui_VectorGeoref()
		self.ui.setupUi(self)
		self.customize_GUI()
		# connect the layer changed handler to a signal that the TOC layer has changed
		QObject.connect(self.iface,SIGNAL("currentLayerChanged(QgsMapLayer *)"), self.myHandleLayerChange)
		# inizializza i dati sul layer
		self.myHandleLayerChange()
		self.newProj()

	def customize_GUI(self):
		# map prevew system
		self.mapPreview = QgsMapCanvas(self)
		self.mapPreview.setCanvasColor(QColor(225,225,225))
		self.ui.tabWidget.addTab(self.mapPreview, "Map Canvas")

	def newProj(self):
		self.firstPntDone = False	# if true pnt fom canvas2, if false pnt from canvas1
		self.isClickToolActivated = 0	# 0-noactive 1-canvas1 2-canvas2

	def on_pushButtonCP_Selection_pressed(self):
		# out click tool will emit a QgsPoint on every click
		self.clickTool1 = QgsMapToolEmitPoint(self.canvas)
		self.clickTool2 = QgsMapToolEmitPoint(self.mapPreview)
		# make our clickTool the tool that we'll use for now
		self.canvas.setMapTool(self.clickTool1)
		self.mapPreview.setMapTool(self.clickTool2)
		self.firstPntDone = False
		self.vecLayGeorefTool()
		
	def on_pushButton_load_layer_pressed(self):
		# ---------- carica il layer da file -----------
		fname = QFileDialog.getOpenFileName(self.iface.mainWindow(),'Open file','/home/giuliano','*.shp')
		if fname:
			print "aperto layer",fname
			layerToSet = []
			self.vLayer = QgsVectorLayer(fname, "layer_prova", "ogr")
			QgsMapLayerRegistry.instance().addMapLayers([self.vLayer], False)
			layerToSet.append(QgsMapCanvasLayer(self.vLayer, True, False))
			self.mapPreview.setLayerSet(layerToSet)
			self.mapPreview.zoomToFullExtent()
			# azzera la tabella dei CP
			self.on_pushButton_clear_pressed()

	def on_pushButton_run_pressed(self):
		# legge i dati della tabella...
		tmp = self.getValues()
		#  .. e li deposita nelle due liste
		srcPntList = []
		dstPntList = []
		for [check,oX,oY,dX,dY] in tmp:
			if check == 'ok':
				srcPntList.append([float(oX),float(oY),1.0])	# aggiunge la coordinata omogenea
				dstPntList.append([float(dX),float(dY),1.0])
#				print "il punto (%s %s) va in (%s %s)" % (oX,oY,dX,dY)
		# ------- trasformazione dei layer ------
		# numero di coppie
		nP = len(srcPntList)
		if nP >= 2:
			vtype = ['Point','Linestring','Polygon']
			if self.vLayer:
				gT = self.vLayer.geometryType()
				if gT in (0,1,2):
					lN = self.vLayer.name()+'-modificato'
					newLayer = self.cloneLayer(self.vLayer,vtype[gT],lN)
					# calcola la matrice ai minimi quadrati
					mat = self.lsm2(srcPntList,dstPntList)
#					self.printMatrix(mat)
					if gT == 0:
#						print "layer puntuale"
						self.pointTransform(newLayer,mat)
					elif gT == 1:
#						print "layer lineare"
						self.lineTransform(newLayer,mat)
					elif gT == 2:
#						print "layer poligonale"
						self.polygTransform(newLayer,mat)
					# Commit changes
					newLayer.commitChanges()
					# set CRS
					render = self.canvas.mapRenderer()
					curCrs = render.destinationCrs()
					newLayer.setCoordinateSystem(curCrs)
					# update layer's extent
					newLayer.updateExtents()
					# user warning
					self.iface.messageBar().pushMessage(
						"on_pushButton_run_pressed",
						"Layer in memory, save it!",
						level=QgsMessageBar.INFO,
						duration=4
					)
				else:
					self.iface.messageBar().pushMessage(
						"on_pushButton_run_pressed",
						"Layer sconosciuto",
						level=QgsMessageBar.CRITICAL,
						duration=4
					)
		else:
			self.iface.messageBar().pushMessage(
				"on_pushButton_run_pressed",
				"Numero di punti insufficiente",
				level=QgsMessageBar.CRITICAL,
				duration=3
			)

	def on_pushButton_clear_pressed(self):
		"""
			Clear the table
		"""
		self.ui.tableWidget.clear()
		self.ui.tableWidget.setRowCount(0)
		# pulisce lo schermo
		self.cleanSelection()

	def on_pushButton_save_CPT_pressed(self):
		"""
			salva i CTP su file
		"""
		if self.vLayer:
			# legge i dati della tabella...
			tmp = self.getValues()
			# crea il file di output
			fname = self.vLayer.name() + '.ctp'
			f = open(fname,'w')
			if f:
				# salva i CRS (source & dest) coinvolti
				srcCrs = self.vLayer.crs().authid()
				curCrs = self.canvas.mapRenderer().destinationCrs().authid()
				f.write("%s %s\n" %(srcCrs,curCrs))
				#  .. e salva i punti
				for [check,oX,oY,dX,dY] in tmp:
					f.write("%s %s %s %s %s\n" % (check,oX,oY,dX,dY))
				f.close()
				self.iface.messageBar().pushMessage(
					"on_pushButton_save_pressed",
					"C(ontrol) T(errain) Points salvati su "+fname,
					level=QgsMessageBar.INFO,
					duration=3
				)
			else:
				self.iface.messageBar().pushMessage(
					"on_pushButton_save_pressed",
					"errore: impossibile aprire il file"+fname,
					level=QgsMessageBar.CRITICAL,
					duration=3
				)
		else:
			self.iface.messageBar().pushMessage(
				"on_pushButton_save_pressed",
				"errore: devi prima aprire il layer e definire i punti di controllo",
				level=QgsMessageBar.CRITICAL,
				duration=3
			)

	def on_pushButton_read_CPT_pressed(self):
		"""
			legge i CTP salvati su file
		"""
		if self.vLayer:
			# pulisce la maschera
			self.on_pushButton_clear_pressed()
			# legge il file di input
			fname = QFileDialog.getOpenFileName(self.iface.mainWindow(),'Open file','/home/giuliano','*.ctp')
			if fname:
				f = open(fname,'r')
				if f:
					tmp = f.readline()
					srcCrs,curCrs = tmp.split(' ')
					srcCrs = srcCrs.rstrip()
					curCrs = curCrs.rstrip()
					if srcCrs != self.vLayer.crs().authid():
						self.iface.messageBar().pushMessage(
							"on_pushButton_read_pressed",
							"errore: il CRS di provenienza non coincide con quello del layer da trasformare",
							level=QgsMessageBar.CRITICAL,
							duration=3
						)
					elif curCrs != self.canvas.mapRenderer().destinationCrs().authid():
						self.iface.messageBar().pushMessage(
							"on_pushButton_read_pressed",
							"errore: il CRS di destinazione non coincide con quello quello corrente",
							level=QgsMessageBar.CRITICAL,
							duration=3
						)
					else:
						for tmp in f:
							check,origX,origY,destX,destY = tmp.split()
							self.insertNewRow([check,origX,origY,destX,destY])
							vertex = QgsPoint(float(origX),float(origY))
							self.markerList2.append(self.pntHighligth(self.mapPreview,vertex,color=QColor(250,150,0),size=25))
							vertex = QgsPoint(float(destX),float(destY))
							self.markerList1.append(self.pntHighligth(self.canvas,vertex,color=QColor(250,150,0),size=25))
				else:
					self.iface.messageBar().pushMessage(
						"on_pushButton_read_pressed",
						"errore: impossibile aprire il file"+fname,
						level=QgsMessageBar.CRITICAL,
						duration=3
					)
			else:
				self.iface.messageBar().pushMessage(
					"on_pushButton_read_pressed",
					"errore: dammi un file valido",
					level=QgsMessageBar.CRITICAL,
					duration=3
				)	
		else:
			self.iface.messageBar().pushMessage(
				"on_pushButton_save_pressed",
				"errore: devi prima aprire il layer e definire i punti di controllo",
				level=QgsMessageBar.CRITICAL,
				duration=3
			)

# ----------- utility functions ----------------

	def myHandleLayerChange(self):
		if self.iface.activeLayer():
			# registra il layer corrente
			self.cLayer = self.iface.activeLayer()

	def pntHighligth(self,canvas,pnt,color=QColor(250,150,0),size=25):
		"""
			attiva il marcatore del punto
			NB: riceve una feature
		"""
		x,y = pnt.x(),pnt.y()
		marker = QgsVertexMarker(canvas)
#		marker.setIconType(QgsVertexMarker.ICON_CROSS)
		marker.setColor(color)
		marker.setIconSize(size)
		marker.setCenter(QgsPoint(x,y))
		marker.show()
		return marker

	def cleanSelection(self):
		"""
			Pulisce lo stack dei selezionati e toglie i marker;
		"""
		# elimina i marcatori
		for m in self.markerList1:
			self.canvas.scene().removeItem(m)
		self.markerList1 = []
		for m in self.markerList2:
			self.mapPreview.scene().removeItem(m)
		self.markerList2 = []
		# rinfresca il video
		self.canvas.refresh()
		self.mapPreview.refresh()

	def insertNewRow(self,dataList):
		"""
			Populate the table row
		"""
		nRow = self.ui.tableWidget.rowCount()
		self.ui.tableWidget.insertRow(nRow)
		for i,val in enumerate(dataList):
			item = QtGui.QTableWidgetItem(unicode(val))
			self.ui.tableWidget.setItem(nRow,i,item)

	def getValues(self):
		"""
			get the table values
		"""
		nRow = self.ui.tableWidget.rowCount()
		nCol = self.ui.tableWidget.columnCount()
		data = []
		for r in range(nRow):
			riga = []
			for c in range(nCol):
				item = self.ui.tableWidget.item(r,c)
				print item.text()
				riga.append(item.text())
			data.append(riga)
		return data

# ------------ georeferencing functions -------------------

	def vecLayGeorefTool(self):
		"""
			attiva/disattiva/switcha il clickTool

			all'inizio (isFirstPnt == False) spegne se necessario il click1 e attiva il click2
			dopo il primo punto spegne il click2 ed attiva il click1
		"""
		if self.firstPntDone:
			# prepara il punto destinazione
			# try to disconnect all signals
			if self.isClickToolActivated == 2:
				self.clickTool2.canvasClicked.disconnect()
			# connect to click signal 1
			QObject.connect(
				self.clickTool1,
				SIGNAL("canvasClicked(const QgsPoint &, Qt::MouseButton)"),
				self.vecLayGeoref
			)
			self.isClickToolActivated = 1
			QMessageBox.information(
				self.iface.mainWindow(),
				'vecLayGeoref',
				"ora dammi punto destinazione"
			)
		else:
			# prepara il punto origine
			# try to disconnect all signals
			if self.isClickToolActivated == 1:
				self.clickTool1.canvasClicked.disconnect()
			# connect to click signal 2
			QObject.connect(
				self.clickTool2,
				SIGNAL("canvasClicked(const QgsPoint &, Qt::MouseButton)"),
				self.vecLayGeoref
			)
			self.isClickToolActivated = 2
			QMessageBox.information(
				self.iface.mainWindow(),
				'vecLayGeoref',
				"dammi punto origine"
			)

	def vecLayGeoref(self,point):
		"""
		esegue la selezione dei ctp
		quì il primo punto è origine, il secondo destinazione

		NB: controllare che i punti non coincidano
		"""
		if self.isClickToolActivated == 2:
			# trasforma in screen coordinates
			newPoint = self.mapPreview.getCoordinateTransform().transform(point)
			# .. e in QPoint
			pnt = QPoint(newPoint.x(),newPoint.y())
			# attiva lo snapper
			mySnapper = QgsMapCanvasSnapper(self.mapPreview)
			(reval, snapped) = mySnapper.snapToBackgroundLayers(pnt)
			if snapped != []:
				vertex = QgsPoint(snapped[0].snappedVertex.x(), snapped[0].snappedVertex.y())
				self.origX,self.origY = vertex.x(),vertex.y()
#				print "punto origine",self.origX,self.origY
				self.markerList2.append(self.pntHighligth(self.mapPreview,vertex,color=QColor(250,150,0),size=25))
				self.firstPntDone = True
				self.vecLayGeorefTool()
			else:
				QMessageBox.information(
					self.iface.mainWindow(),
					'vecLayGeoref',
					"nessun punto individuato"
				)
		else:
			# trasforma in screen coordinates
			newPoint = self.canvas.getCoordinateTransform().transform(point)
			# .. e in QPoint
			pnt = QPoint(newPoint.x(),newPoint.y())
			# attiva lo snapper
			mySnapper = QgsMapCanvasSnapper(self.canvas)
			(reval, snapped) = mySnapper.snapToCurrentLayer(pnt,QgsSnapper.SnapToVertex)
			if snapped != []:
				vertex = QgsPoint(snapped[0].snappedVertex.x(), snapped[0].snappedVertex.y())
				destX,destY = vertex.x(),vertex.y()
#				print "punto destinazione",destX,destY
				self.markerList1.append(self.pntHighligth(self.canvas,vertex,color=QColor(250,150,0),size=25))
				# accoda alla tabella
				self.insertNewRow(['ok',self.origX,self.origY,destX,destY])
				# try to disconnect all signals
				if self.isClickToolActivated == 1:
					self.clickTool1.canvasClicked.disconnect()
					self.isClickToolActivated = 0
			else:
				QMessageBox.information(
					self.iface.mainWindow(),
					'vecLayGeoref',
					"nessun punto individuato"
				)

	# -------- layer functions -------

	def cloneLayer(self, oldLayer,type,name):
		"""
			clone the layer in newlayer
		"""
		newLayer = QgsVectorLayer()
		# copia gli attributi
		oProv = oldLayer.dataProvider()
		myAttrList = oProv.fields()
		# copia il CRS
		myCrs = oldLayer.crs()
		# creo il nuovo layer
		newLayer = QgsVectorLayer(type,name,"memory")				
		# Enter editing mode
		newLayer.startEditing()
		# setta il crs
		newLayer.setCrs(myCrs)
		# aggiunge gli attributi
		nProv = newLayer.dataProvider()
		for att in myAttrList:
			nProv.addAttributes([att])
		# duplica le features
		for feat in oldLayer.getFeatures():
			nProv.addFeatures([feat])
		# aggiunge al registry
		QgsMapLayerRegistry.instance().addMapLayer(newLayer)
		return newLayer

	def pointTransform(self, layer,matrix):
		"""
			Esegue la trasformazione di un layer puntuale
			questa forma non mi piace però la gestione degli attributi è
			piuttosto ostica e questa sembra funzionare
		"""
		for feat in layer.getFeatures():
			geom = feat.geometry()
			p = geom.asPoint()
			cds = self.matrixMultiplication(matrix,[[p.x()],[p.y()],[1]])
	#		print cds
			geom = QgsGeometry.fromPoint(QgsPoint(cds[0][0],cds[1][0]))
			layer.changeGeometry(feat.id(),geom)

	def lineTransform(self, layer,matrix):
		"""
			Esegue la trasformazione di un layer lineare
		"""
		for feat in layer.getFeatures():
			geom = feat.geometry()
			line = geom.asPolyline()
			# costruisce la nuova
			newLine = []
			for p in line:
				cds = self.matrixMultiplication(matrix,[[p.x()],[p.y()],[1]])
	#			print cds
				newLine.append(QgsPoint(cds[0][0],cds[1][0]))
			geom = QgsGeometry.fromPolyline(newLine)
			layer.changeGeometry(feat.id(),geom)

	def polygTransform(self, layer,matrix):
		"""
			Esegue la trasformazione di un layer poligonale
		"""
		for feat in layer.getFeatures():
			geom = feat.geometry()
			plgns = geom.asPolygon()
			# nuova geometria
			newPlgns = []
			for line in plgns:
				# costruisce il nuovo poligono
				newLine = []
				for v in line:
					cds = self.matrixMultiplication(matrix,[[v.x()],[v.y()],[1]])
	#				print cds
					newLine.append(QgsPoint(cds[0][0],cds[1][0]))
				# aggiorna la geometria
				newPlgns.append(newLine)
			geom = QgsGeometry.fromPolygon(newPlgns)
			layer.changeGeometry(feat.id(),geom)