# -*- 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:

" ).append( errors.join( "
" ) ) 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 )