# -*- 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 Qt, QObject, SIGNAL, QThread, QMutex from PyQt4.QtGui import QDialog, QDialogButtonBox, QListWidgetItem, QAbstractItemView, QErrorMessage, QMessageBox from qgis.core import QGis, QgsProviderRegistry, QgsVectorLayer, QgsVectorDataProvider 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 errors: msg = self.tr("Processing of the following layers/files ended with error:

") + "
".join(errors) QErrorMessage(self).showMessage(msg) QMessageBox.information(self, self.tr("Finished"), self.tr("Processing completed.")) def stopProcessing(self): if self.workThread is not 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 = [] 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)