QGIS/python/plugins/fTools/tools/doSpatialIndex.py
2012-01-26 00:54:56 +01:00

222 lines
7.2 KiB
Python

# -*- coding: utf-8 -*-
"""
***************************************************************************
doSpatialIndex.py - build spatial index for vector layers or files
--------------------------------------
Date : 11-Nov-2011
Copyright : (C) 2011 by Alexander Bruy
Email : alexander dot bruy at gmail dot com
***************************************************************************
* *
* 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. *
* *
***************************************************************************
"""
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from qgis.core import *
from qgis.gui import *
import ftools_utils
from ui_frmSpatialIndex import Ui_Dialog
class Dialog( QDialog, Ui_Dialog ):
def __init__( self, iface ):
QDialog.__init__( self, iface.mainWindow() )
self.setupUi( self )
self.iface = iface
self.workThread = None
self.btnOk = self.buttonBox.button( QDialogButtonBox.Ok )
self.btnClose = self.buttonBox.button( QDialogButtonBox.Close )
QObject.connect( self.chkExternalFiles, SIGNAL( "stateChanged( int )" ), self.toggleExternalFiles )
QObject.connect( self.btnSelectFiles, SIGNAL( "clicked()" ), self.selectFiles )
QObject.connect( self.lstLayers, SIGNAL( "itemSelectionChanged()" ), self.updateLayerList )
QObject.connect( self.btnSelectAll, SIGNAL( "clicked()" ), self.selectAll )
QObject.connect( self.btnSelectNone, SIGNAL( "clicked()" ), self.selectNone )
QObject.connect( self.btnClearList, SIGNAL( "clicked()" ), self.clearList )
self.manageGui()
def manageGui( self ):
self.btnSelectFiles.setEnabled( False )
self.btnClearList.setEnabled( False )
self.fillLayersList()
def fillLayersList( self ):
self.lstLayers.clear()
layers = ftools_utils.getLayerNames( [ QGis.Line, QGis.Point, QGis.Polygon ] )
for lay in layers:
source = ftools_utils.getVectorLayerByName( lay ).source()
item = QListWidgetItem( lay, self.lstLayers )
item.setData( Qt.UserRole, source )
item.setData( Qt.ToolTipRole, source )
def toggleExternalFiles( self ):
if self.chkExternalFiles.isChecked():
self.btnSelectFiles.setEnabled( True )
self.btnClearList.setEnabled( True )
self.btnSelectAll.setEnabled( False )
self.btnSelectNone.setEnabled( False )
self.lstLayers.clear()
self.lstLayers.setSelectionMode( QAbstractItemView.NoSelection )
self.layers = []
else:
self.btnSelectFiles.setEnabled( False )
self.btnClearList.setEnabled( False )
self.btnSelectAll.setEnabled( True )
self.btnSelectNone.setEnabled( True )
self.fillLayersList()
self.lstLayers.setSelectionMode( QAbstractItemView.ExtendedSelection )
self.updateLayerList()
def updateLayerList( self ):
self.layers = []
selection = self.lstLayers.selectedItems()
for item in selection:
self.layers.append( item.text() )
def selectFiles( self ):
filters = QgsProviderRegistry.instance().fileVectorFilters()
( files, self.encoding ) = ftools_utils.openDialog( self, filtering = filters, dialogMode = "MultipleFiles" )
if files is None:
return
self.layers.extend( [ unicode( f ) for f in files ] )
self.lstLayers.addItems( files )
def selectAll( self ):
self.lstLayers.selectAll()
def selectNone( self ):
self.lstLayers.clearSelection()
def clearList( self ):
self.layers = []
self.lstLayers.clear()
def accept( self ):
self.btnOk.setEnabled( False )
self.workThread = SpatialIdxThread( self.layers, self.chkExternalFiles.isChecked() )
self.progressBar.setRange( 0, len( self.layers ) )
QObject.connect( self.workThread, SIGNAL( "layerProcessed()" ), self.layerProcessed )
QObject.connect( self.workThread, SIGNAL( "processFinished( PyQt_PyObject )" ), self.processFinished )
QObject.connect( self.workThread, SIGNAL( "processInterrupted()" ), self.processInterrupted )
self.btnClose.setText( self.tr( "Cancel" ) )
QObject.disconnect( self.buttonBox, SIGNAL( "rejected()" ), self.reject )
QObject.connect( self.btnClose, SIGNAL( "clicked()" ), self.stopProcessing )
self.workThread.start()
def layerProcessed( self ):
self.progressBar.setValue( self.progressBar.value() + 1 )
def processInterrupted( self ):
self.restoreGui()
def processFinished( self, errors ):
self.stopProcessing()
self.restoreGui()
if not errors.isEmpty():
msg = QString( "Processing of the following layers/files ended with error:<br><br>" ).append( errors.join( "<br>" ) )
QErrorMessage( self ).showMessage( msg )
QMessageBox.information( self, self.tr( "Finished" ), self.tr( "Processing completed." ) )
def stopProcessing( self ):
if self.workThread != None:
self.workThread.stop()
self.workThread = None
def restoreGui( self ):
self.progressBar.setValue( 0 )
QObject.connect( self.buttonBox, SIGNAL( "rejected()" ), self.reject )
self.btnClose.setText( self.tr( "Close" ) )
self.btnOk.setEnabled( True )
if self.chkExternalFiles.isChecked():
self.clearList()
class SpatialIdxThread( QThread ):
def __init__( self, layers, isFiles ):
QThread.__init__( self, QThread.currentThread() )
self.layers = layers
self.isFiles = isFiles
self.mutex = QMutex()
self.stopMe = 0
self.errors = QStringList()
def run( self ):
self.mutex.lock()
self.stopMe = 0
self.mutex.unlock()
interrupted = False
if self.isFiles:
for layer in self.layers:
vl = QgsVectorLayer( layer, "tmp", "ogr" )
provider = vl.dataProvider()
if provider.capabilities() & QgsVectorDataProvider.CreateSpatialIndex:
if not provider.createSpatialIndex():
self.errors.append( layer )
else:
self.errors.append( layer )
self.emit( SIGNAL( "layerProcessed()" ) )
self.mutex.lock()
s = self.stopMe
self.mutex.unlock()
if s == 1:
interrupted = True
break
else:
for layer in self.layers:
vl = ftools_utils.getVectorLayerByName( layer )
provider = vl.dataProvider()
if provider.capabilities() & QgsVectorDataProvider.CreateSpatialIndex:
if not provider.createSpatialIndex():
self.errors.append( layer )
else:
self.errors.append( layer )
self.emit( SIGNAL( "layerProcessed()" ) )
self.mutex.lock()
s = self.stopMe
self.mutex.unlock()
if s == 1:
interrupted = True
break
if not interrupted:
self.emit( SIGNAL( "processFinished( PyQt_PyObject )" ), self.errors )
else:
self.emit( SIGNAL( "processInterrupted()" ) )
def stop( self ):
self.mutex.lock()
self.stopMe = 1
self.mutex.unlock()
QThread.wait( self )