def reconnectCsvVectorLayers(self, csvVectorLayers): layers = QgsMapLayerRegistry.instance().mapLayers() for qgsLayer in layers.itervalues(): csvFilePath = qgsLayer.customProperty('editablegeocsv_path', '') if csvFilePath: try: dataSourceHandler = GeoCsvDataSourceHandler(csvFilePath) vectorLayerDescriptor = dataSourceHandler.createCsvVectorDescriptorFromCsvt() if not dataSourceHandler.hasPrj(): dataSourceHandler.updatePrjFile(qgsLayer.crs().toWkt()) csvVectorLayer = GeoCsvVectorLayerFactory.createCsvVectorLayer(dataSourceHandler, vectorLayerDescriptor, qgsLayer) vectorLayerController = VectorLayerController(csvVectorLayer, dataSourceHandler) csvVectorLayer.initController(vectorLayerController) csvVectorLayers.append(csvVectorLayer) NotificationHandler.pushSuccess(QApplication.translate('GeoCsvReconnectController', 'GeoCSV Layer reconnected'), QApplication.translate('GeoCsvReconnectController', 'Layer "{}" is successfully reconnected').format(qgsLayer.name())) except: GeoCsvNewController.getInstance().createCsvVectorLayer(csvVectorLayers, qgsLayer, QApplication.translate('GeoCsvReconnectController', 'Couldn\'t automatically restore csv layer "{}"').format(qgsLayer.name()))
class GeoCsvNewController: _instance = None def __init__(self, projectSettings): ':type projectSettings:QSettings' self.geometryFieldUpdate = False self.csvtFileIsDirty = False self.newDialog = GeoCsvDialogNew() self._initConnections() self._initVisibility() self._settings = projectSettings self._browseOpenPath = self._getDefaultFileOpenDir(projectSettings) def _getDefaultFileOpenDir(self, settings): ':type settings:QSettings' openDir = settings.value('lastUsedFileOpenDir', '') if not openDir: absoluteProjectPath = QgsProject.instance().readPath("./") openDir = QDesktopServices.storageLocation(QDesktopServices.HomeLocation) if absoluteProjectPath == "./" else absoluteProjectPath return openDir def _updateDefaultFileOpenDir(self, newPath): self._settings.setValue('lastUsedFileOpenDir', newPath) def createCsvVectorLayer(self, csvVectorLayers, qgsVectorLayer=None, customTitle=None): if self.newDialog.isVisible(): self.newDialog.reject() # enable help hyperlink self.newDialog.helpLabel.setOpenExternalLinks(True) self.dataSourceHandler = None self.vectorDescriptor = None self.csvtFileIsDirty = False if customTitle: self.newDialog.setWindowTitle(customTitle) if qgsVectorLayer: csvPath = qgsVectorLayer.customProperty('editablegeocsv_path') if csvPath: self.newDialog.filePath.setText(csvPath) self._updateAcceptButton() self._analyseCsv() self.newDialog.show() #wait for user input result = self.newDialog.exec_() #if user pressed ok if result == 1: if self.dataSourceHandler and self.vectorDescriptor: csvVectorLayer = GeoCsvVectorLayerFactory.createCsvVectorLayer(self.dataSourceHandler, self.vectorDescriptor, qgsVectorLayer) vectorLayerController = VectorLayerController(csvVectorLayer, self.dataSourceHandler) csvVectorLayer.initController(vectorLayerController) QgsMapLayerRegistry.instance().addMapLayer(csvVectorLayer.qgsVectorLayer) NotificationHandler.pushSuccess(QApplication.translate('GeoCsvNewController', 'GeoCSV Layer created'), QApplication.translate('GeoCsvNewController', 'The layer "{}" was created successfully.').format(csvVectorLayer.qgsVectorLayer.name())) csvVectorLayers.append(csvVectorLayer) if self.csvtFileIsDirty: try: self.dataSourceHandler.updateCsvtFile(self.vectorDescriptor.getAttributeTypes()) NotificationHandler.pushInfo(QApplication.translate('GeoCsvNewController', 'CSVT File created/updated.'), QApplication.translate('GeoCsvNewController', 'The CSVT file was successfully created/updated on disk.')) except FileIOException: NotificationHandler.pushWarning(QApplication.translate('GeoCsvNewController', 'CSVT File Error'), QApplication.translate('GeoCsvNewController', 'The csvt file couldn\'t be updated on disk.')) if not self.dataSourceHandler.hasPrj(): self.dataSourceHandler.updatePrjFile(csvVectorLayer.qgsVectorLayer.crs().toWkt()) NotificationHandler.pushInfo(QApplication.translate('GeoCsvNewController', 'PRJ File created.'), QApplication.translate('GeoCsvNewController', 'The PRJ file was successfully created on disk.')) def _initConnections(self): self.newDialog.fileBrowserButton.clicked.connect(self._onFileBrowserButton) self.newDialog.filePath.textChanged.connect(self._analyseCsv) self.newDialog.acceptButton.clicked.connect(self.newDialog.accept) self.newDialog.rejectButton.clicked.connect(self.newDialog.reject) self.newDialog.pointGeometryTypeRadio.toggled.connect(self._toggleGeometryType) self.newDialog.wktGeometryTypeRadio.toggled.connect(self._toggleGeometryType) self.newDialog.northingAttributeDropDown.currentIndexChanged.connect(self._createVectorDescriptorFromGeometryTypeWidget) self.newDialog.eastingAttributeDropDown.currentIndexChanged.connect(self._createVectorDescriptorFromGeometryTypeWidget) self.newDialog.wktAttributeDropDown.currentIndexChanged.connect(self._createVectorDescriptorFromGeometryTypeWidget) self.newDialog.charsetConvertButton.clicked.connect(self._onCharsetConvert) def _initVisibility(self): self._hideGeometryTypeWidget() self._toggleGeometryType() self.newDialog.charsetWidget.hide() def _analyseCsv(self): self.dataSourceHandler = None self.vectorDescriptor = None csvFilePath = self.newDialog.filePath.text() if csvFilePath: try: self._updateDataSource(csvFilePath) self._hideCharsetWidget() except InvalidDataSourceException as e: self.newDialog.statusNotificationLabel.setText(QApplication.translate('GeoCsvNewController', 'invalid file path')) self._hideGeometryTypeWidget() self._hideCharsetWidget() except InvalidDelimiterException as e: #currently not tested self.newDialog.statusNotificationLabel.setText(QApplication.translate('GeoCsvNewController', 'invalid delimiter. expected "{}"').format(e.expectedDelimiter)) self._hideGeometryTypeWidget() self._hideCharsetWidget() except UnicodeDecodeError: self._hideGeometryTypeWidget() self._onCharsetError() else: self._createVectorDescriptorFromCsvt() self._hideCharsetWidget() self._showGeometryTypeWidget() else: self.newDialog.statusNotificationLabel.setText("") self._updateAcceptButton() def _onFileBrowserButton(self): csvFilePath = QFileDialog.getOpenFileName(self.newDialog, QApplication.translate('GeoCsvNewController', 'Open GeoCSV File'), self._browseOpenPath, QApplication.translate('GeoCsvNewController', 'Files (*.csv *.tsv *.*)')) if csvFilePath: self._updateDefaultFileOpenDir(QFileInfo(csvFilePath).path()) self.newDialog.filePath.setText(csvFilePath) self.newDialog.activateWindow() def _onCharsetError(self): self.newDialog.statusNotificationLabel.setText(QApplication.translate('GeoCsvNewController', 'not utf8 encoded')) self.newDialog.charsetDropDown.addItems(CharsetList.charsetList) self.newDialog.charsetDropDown.setCurrentIndex(CharsetList.charsetList.index("latin_1")) self._showCharsetWidget() def _onCharsetConvert(self): csvFilePath = self.newDialog.filePath.text() encoding = self.newDialog.charsetDropDown.currentText() try: GeoCsvDataSourceHandler.createBackupFile(csvFilePath) NotificationHandler.pushInfo(QApplication.translate('GeoCsvNewController', 'backup created'), QApplication.translate('GeoCsvNewController', 'Created backup on "{}"').format(csvFilePath)) GeoCsvDataSourceHandler.convertFileToUTF8(csvFilePath, encoding) NotificationHandler.pushSuccess(QApplication.translate('GeoCsvNewController', 'Converted'), QApplication.translate('GeoCsvNewController', 'Successfully converted to utf-8')) self._analyseCsv() except: self.newDialog.statusNotificationLabel.setText(QApplication.translate('GeoCsvNewController', 'error in converting')) def _hideCharsetWidget(self): self.newDialog.charsetWidget.hide() def _showCharsetWidget(self): self.newDialog.charsetWidget.show() def _updateDataSource(self, csvFilePath, csvEncoding=None): try: self.dataSourceHandler = GeoCsvDataSourceHandler(csvFilePath) except (InvalidDataSourceException, UnicodeDecodeError): raise def _createVectorDescriptorFromCsvt(self): try: self.vectorDescriptor = self.dataSourceHandler.createCsvVectorDescriptorFromCsvt() self.newDialog.statusNotificationLabel.setText("") except GeoCsvUnknownAttributeException as e: self.newDialog.statusNotificationLabel.setText(QApplication.translate('GeoCsvNewController', 'unknown csvt attribute: {}').format(e.attributeName)) except CsvCsvtMissmatchException: self.newDialog.statusNotificationLabel.setText(QApplication.translate('GeoCsvNewController', 'csv<->csvt missmatch')) except GeoCsvMalformedGeoAttributeException: self.newDialog.statusNotificationLabel.setText(QApplication.translate('GeoCsvNewController', 'csvt file contains incorrect geo attributes')) except GeoCsvMultipleGeoAttributeException: self.newDialog.statusNotificationLabel.setText(QApplication.translate('GeoCsvNewController', 'csvt file contains too many geo attributes')) except GeoCsvUnknownGeometryTypeException: self.newDialog.statusNotificationLabel.setText(QApplication.translate('GeoCsvNewController', 'csvt geometry type exception')) except: self.newDialog.statusNotificationLabel.setText(QApplication.translate('GeoCsvNewController', 'no csvt file found')) def _createVectorDescriptorFromGeometryTypeWidget(self, index): if not self.geometryFieldUpdate: self.vectorDescriptor = None self.newDialog.statusNotificationLabel.setText("") if not index == 0: try: if self.newDialog.pointGeometryTypeRadio.isChecked(): if not self.newDialog.eastingAttributeDropDown.currentIndex() == 0 and not self.newDialog.northingAttributeDropDown.currentIndex() == 0: self.vectorDescriptor = self.dataSourceHandler.manuallyCreateCsvPointVectorDescriptor(self.newDialog.eastingAttributeDropDown.currentIndex() - 1, self.newDialog.northingAttributeDropDown.currentIndex() - 1) else: self.vectorDescriptor = self.dataSourceHandler.manuallyCreateCsvWktVectorDescriptor(self.newDialog.wktAttributeDropDown.currentIndex() - 1) except: self.newDialog.statusNotificationLabel.setText(QApplication.translate('GeoCsvNewController', 'error in geometry selection')) if self.vectorDescriptor: self.csvtFileIsDirty = True self._updateAcceptButton() def _updateGeometryTypeLists(self): try: attributeNames = self.dataSourceHandler.extractAttributeNamesFromCsv() except: self.newDialog.statusNotificationLabel.setText(QApplication.translate('GeoCsvNewController', 'error while loading csv')) else: self.geometryFieldUpdate = True self.newDialog.eastingAttributeDropDown.clear() self.newDialog.eastingAttributeDropDown.addItem("----") self.newDialog.eastingAttributeDropDown.addItems(attributeNames) self.newDialog.northingAttributeDropDown.clear() self.newDialog.northingAttributeDropDown.addItem("----") self.newDialog.northingAttributeDropDown.addItems(attributeNames) self.newDialog.wktAttributeDropDown.clear() self.newDialog.wktAttributeDropDown.addItem("----") self.newDialog.wktAttributeDropDown.addItems(attributeNames) if self.vectorDescriptor: if self.vectorDescriptor.descriptorType == CsvVectorLayerDescriptor.pointDescriptorType: self.newDialog.pointGeometryTypeRadio.setChecked(True) self.newDialog.eastingAttributeDropDown.setCurrentIndex(self.vectorDescriptor.eastingIndex + 1) self.newDialog.northingAttributeDropDown.setCurrentIndex(self.vectorDescriptor.northingIndex + 1) else: self.newDialog.wktGeometryTypeRadio.setChecked(True) self.newDialog.wktAttributeDropDown.setCurrentIndex(self.vectorDescriptor.wktIndex + 1) self.geometryFieldUpdate = False def _toggleGeometryType(self): if self.newDialog.pointGeometryTypeRadio.isChecked(): self.newDialog.wktTypeWidget.hide() self.newDialog.pointTypeWidget.show() else: self.newDialog.pointTypeWidget.hide() self.newDialog.wktTypeWidget.show() def _showGeometryTypeWidget(self): self._updateGeometryTypeLists() self._toggleGeometryType() self.newDialog.geometryWidget.show() def _hideGeometryTypeWidget(self): self.newDialog.geometryWidget.hide() def _updateAcceptButton(self): self.newDialog.acceptButton.setEnabled(self._isValid()) if self._isValid(): self.newDialog.acceptButton.setFocus() def _isValid(self): return not self.dataSourceHandler == None and not self.vectorDescriptor == None
def test_WktTypeRecognition(self): pathToCsvFile = TestCsvLayer.pathToTesResources + "geocsv_sample_wkt.csv" dataSourceHandler = GeoCsvDataSourceHandler(pathToCsvFile) #: :type descriptor: WktCsvVectorDescriptor descriptor = dataSourceHandler.createCsvVectorDescriptorFromCsvt() self.assertEqual(GeometryType.point, descriptor.geometryType)
def test_CreateVectorDescriptorFromCSVT(self): pathToCsvFile = TestCsvLayer.pathToTesResources + "geocsv_sample_point.csv" dataSourceHandler = GeoCsvDataSourceHandler(pathToCsvFile) descriptor = dataSourceHandler.createCsvVectorDescriptorFromCsvt() self.assertEqual(CsvVectorLayerDescriptor.pointDescriptorType, descriptor.descriptorType)