mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-27 00:33:48 -05:00
224 lines
7.8 KiB
Python
224 lines
7.8 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 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:<br><br>") + "<br>".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)
|