From 973d3515d12a9a2f61460827d7839cf40ca92796 Mon Sep 17 00:00:00 2001 From: Matthias Kuhn Date: Sun, 30 Jul 2017 21:51:22 +0200 Subject: [PATCH 1/7] Avoid endless wait cursors --- .../plugins/MetaSearch/dialogs/maindialog.py | 70 +++++++------------ python/plugins/db_manager/db_manager.py | 68 ++++++++---------- .../algs/qgis/ui/FieldsCalculatorDialog.py | 10 ++- python/plugins/processing/gui/ConfigDialog.py | 8 +-- python/utils.py | 22 ++++++ 5 files changed, 85 insertions(+), 93 deletions(-) diff --git a/python/plugins/MetaSearch/dialogs/maindialog.py b/python/plugins/MetaSearch/dialogs/maindialog.py index 9f117acb15c..0d330735fa6 100644 --- a/python/plugins/MetaSearch/dialogs/maindialog.py +++ b/python/plugins/MetaSearch/dialogs/maindialog.py @@ -46,6 +46,7 @@ from qgis.core import (QgsApplication, QgsCoordinateReferenceSystem, QgsCoordinateTransform, QgsGeometry, QgsPointXY, QgsProviderRegistry, QgsSettings) from qgis.gui import QgsRubberBand +from qgis.utils import OverrideCursor from owslib.csw import CatalogueServiceWeb # spellok from owslib.fes import BBox, PropertyIsLike @@ -281,8 +282,6 @@ class MetaSearchDialog(QDialog, BASE_CLASS): if not self._get_csw(): return - QApplication.restoreOverrideCursor() - if self.catalog: # display service metadata self.btnCapabilities.setEnabled(True) metadata = render_template('en', self.context, @@ -490,25 +489,22 @@ class MetaSearchDialog(QDialog, BASE_CLASS): # TODO: allow users to select resources types # to find ('service', 'dataset', etc.) try: - self.catalog.getrecords2(constraints=self.constraints, - maxrecords=self.maxrecords, esn='full') + with OverrideCursor(Qt.WaitCursor): + self.catalog.getrecords2(constraints=self.constraints, + maxrecords=self.maxrecords, esn='full') except ExceptionReport as err: - QApplication.restoreOverrideCursor() QMessageBox.warning(self, self.tr('Search error'), self.tr('Search error: {0}').format(err)) return except Exception as err: - QApplication.restoreOverrideCursor() QMessageBox.warning(self, self.tr('Connection error'), self.tr('Connection error: {0}').format(err)) return if self.catalog.results['matches'] == 0: - QApplication.restoreOverrideCursor() self.lblResults.setText(self.tr('0 results')) return - QApplication.restoreOverrideCursor() self.display_results() def display_results(self): @@ -675,25 +671,20 @@ class MetaSearchDialog(QDialog, BASE_CLASS): else: return - QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) - try: - self.catalog.getrecords2(constraints=self.constraints, - maxrecords=self.maxrecords, - startposition=self.startfrom, esn='full') + with OverrideCursor(Qt.WaitCursor): + self.catalog.getrecords2(constraints=self.constraints, + maxrecords=self.maxrecords, + startposition=self.startfrom, esn='full') except ExceptionReport as err: - QApplication.restoreOverrideCursor() QMessageBox.warning(self, self.tr('Search error'), self.tr('Search error: {0}').format(err)) return except Exception as err: - QApplication.restoreOverrideCursor() QMessageBox.warning(self, self.tr('Connection error'), self.tr('Connection error: {0}').format(err)) return - QApplication.restoreOverrideCursor() - self.display_results() def add_to_ows(self): @@ -727,8 +718,6 @@ class MetaSearchDialog(QDialog, BASE_CLASS): stype = ['ESRI:ArcGIS:FeatureServer', 'afs', 'arcgisfeatureserver'] data_url = item_data['afs'].split('FeatureServer')[0] + 'FeatureServer' - QApplication.restoreOverrideCursor() - sname = '%s from MetaSearch' % stype[1] # store connection @@ -820,14 +809,13 @@ class MetaSearchDialog(QDialog, BASE_CLASS): identifier = get_item_data(item, 'identifier') try: - QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) - cat = CatalogueServiceWeb(self.catalog_url, timeout=self.timeout, # spellok - username=self.catalog_username, - password=self.catalog_password) - cat.getrecordbyid( - [self.catalog.records[identifier].identifier]) + with OverrideCursor(Qt.WaitCursor): + cat = CatalogueServiceWeb(self.catalog_url, timeout=self.timeout, # spellok + username=self.catalog_username, + password=self.catalog_password) + cat.getrecordbyid( + [self.catalog.records[identifier].identifier]) except ExceptionReport as err: - QApplication.restoreOverrideCursor() QMessageBox.warning(self, self.tr('GetRecords error'), self.tr('Error getting response: {0}').format(err)) return @@ -835,11 +823,8 @@ class MetaSearchDialog(QDialog, BASE_CLASS): QMessageBox.warning(self, self.tr('Record parsing error'), self.tr('Unable to locate record identifier')) - QApplication.restoreOverrideCursor() return - QApplication.restoreOverrideCursor() - record = cat.records[identifier] record.xml_url = cat.request @@ -902,21 +887,20 @@ class MetaSearchDialog(QDialog, BASE_CLASS): """convenience function to init owslib.csw.CatalogueServiceWeb""" # spellok # connect to the server - try: - QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) - self.catalog = CatalogueServiceWeb(self.catalog_url, # spellok - timeout=self.timeout, - username=self.catalog_username, - password=self.catalog_password) - return True - except ExceptionReport as err: - msg = self.tr('Error connecting to service: {0}').format(err) - except ValueError as err: - msg = self.tr('Value Error: {0}').format(err) - except Exception as err: - msg = self.tr('Unknown Error: {0}').format(err) + with OverrideCursor(Qt.WaitCursor): + try: + self.catalog = CatalogueServiceWeb(self.catalog_url, # spellok + timeout=self.timeout, + username=self.catalog_username, + password=self.catalog_password) + return True + except ExceptionReport as err: + msg = self.tr('Error connecting to service: {0}').format(err) + except ValueError as err: + msg = self.tr('Value Error: {0}').format(err) + except Exception as err: + msg = self.tr('Unknown Error: {0}').format(err) - QApplication.restoreOverrideCursor() QMessageBox.warning(self, self.tr('CSW Connection error'), msg) return False diff --git a/python/plugins/db_manager/db_manager.py b/python/plugins/db_manager/db_manager.py index cff0672ff2d..cbd43fb2855 100644 --- a/python/plugins/db_manager/db_manager.py +++ b/python/plugins/db_manager/db_manager.py @@ -32,6 +32,8 @@ from qgis.PyQt.QtGui import QIcon, QKeySequence from qgis.gui import QgsMessageBar from qgis.core import QgsSettings, QgsMapLayer +from qgis.utils import OverrideCursor + from .info_viewer import InfoViewer from .table_viewer import TableViewer from .layer_preview import LayerPreview @@ -72,29 +74,23 @@ class DBManager(QMainWindow): QMainWindow.closeEvent(self, e) def refreshItem(self, item=None): - QApplication.setOverrideCursor(Qt.WaitCursor) - try: - if item is None: - item = self.tree.currentItem() - self.tree.refreshItem(item) # refresh item children in the db tree - except BaseError as e: - DlgDbError.showError(e, self) - return - finally: - QApplication.restoreOverrideCursor() + with OverrideCursor(Qt.WaitCursor): + try: + if item is None: + item = self.tree.currentItem() + self.tree.refreshItem(item) # refresh item children in the db tree + except BaseError as e: + DlgDbError.showError(e, self) def itemChanged(self, item): - QApplication.setOverrideCursor(Qt.WaitCursor) - try: - self.reloadButtons() - # clear preview, this will delete the layer in preview tab - self.preview.loadPreview(None) - self.refreshTabs() - except BaseError as e: - DlgDbError.showError(e, self) - return - finally: - QApplication.restoreOverrideCursor() + with OverrideCursor(Qt.WaitCursor): + try: + self.reloadButtons() + # clear preview, this will delete the layer in preview tab + self.preview.loadPreview(None) + self.refreshTabs() + except BaseError as e: + DlgDbError.showError(e, self) def reloadButtons(self): db = self.tree.currentDatabase() @@ -114,14 +110,11 @@ class DBManager(QMainWindow): self._lastDb.registerAllActions(self) def tabChanged(self, index): - QApplication.setOverrideCursor(Qt.WaitCursor) - try: - self.refreshTabs() - except BaseError as e: - DlgDbError.showError(e, self) - return - finally: - QApplication.restoreOverrideCursor() + with OverrideCursor(Qt.WaitCursor): + try: + self.refreshTabs() + except BaseError as e: + DlgDbError.showError(e, self) def refreshTabs(self): index = self.tabs.currentIndex() @@ -300,17 +293,12 @@ class DBManager(QMainWindow): This method takes care to override and restore the cursor, but also catches exceptions and displays the error dialog. """ - QApplication.setOverrideCursor(Qt.WaitCursor) - try: - callback(self.tree.currentItem(), self.sender(), self, *params) - - except BaseError as e: - # catch database errors and display the error dialog - DlgDbError.showError(e, self) - return - - finally: - QApplication.restoreOverrideCursor() + with OverrideCursor(Qt.WaitCursor): + try: + callback(self.tree.currentItem(), self.sender(), self, *params) + except BaseError as e: + # catch database errors and display the error dialog + DlgDbError.showError(e, self) def unregisterAction(self, action, menuName): if not hasattr(self, '_registeredDbActions'): diff --git a/python/plugins/processing/algs/qgis/ui/FieldsCalculatorDialog.py b/python/plugins/processing/algs/qgis/ui/FieldsCalculatorDialog.py index 96f515c8770..275d5abb522 100644 --- a/python/plugins/processing/algs/qgis/ui/FieldsCalculatorDialog.py +++ b/python/plugins/processing/algs/qgis/ui/FieldsCalculatorDialog.py @@ -40,6 +40,7 @@ from qgis.core import (QgsExpressionContextUtils, QgsMapLayerProxyModel, QgsMessageLog) from qgis.gui import QgsEncodingFileDialog +from qgis.utils import OverrideCursor from processing.core.ProcessingConfig import ProcessingConfig from processing.core.ProcessingLog import ProcessingLog @@ -220,10 +221,9 @@ class FieldsCalculatorDialog(BASE, WIDGET): def accept(self): keepOpen = ProcessingConfig.getSetting(ProcessingConfig.KEEP_DIALOG_OPEN) - try: - parameters = self.getParamValues() - if parameters: - QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) + parameters = self.getParamValues() + if parameters: + with OverrideCusor(Qt.WaitCursor): context = dataobjects.createContext() ProcessingLog.addToLog(self.alg.asPythonCommand(parameters, context)) @@ -235,8 +235,6 @@ class FieldsCalculatorDialog(BASE, WIDGET): not keepOpen) if not keepOpen: QDialog.reject(self) - finally: - QApplication.restoreOverrideCursor() def reject(self): self.executed = False diff --git a/python/plugins/processing/gui/ConfigDialog.py b/python/plugins/processing/gui/ConfigDialog.py index 207cb03c211..3286321a316 100644 --- a/python/plugins/processing/gui/ConfigDialog.py +++ b/python/plugins/processing/gui/ConfigDialog.py @@ -51,6 +51,7 @@ from qgis.gui import (QgsDoubleSpinBox, QgsSpinBox, QgsOptionsPageWidget) from qgis.core import NULL, QgsApplication, QgsSettings +from qgis.utils import OverrideCursor from processing.core.ProcessingConfig import (ProcessingConfig, settingsWatcher, @@ -293,10 +294,9 @@ class ConfigDialog(BASE, WIDGET): return setting.save(qsettings) - QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) - for p in QgsApplication.processingRegistry().providers(): - p.refreshAlgorithms() - QApplication.restoreOverrideCursor() + with OverrideCursor(Qt.WaitCursor): + for p in QgsApplication.processingRegistry().providers(): + p.refreshAlgorithms() settingsWatcher.settingsChanged.emit() diff --git a/python/utils.py b/python/utils.py index 8edb904b6c0..205ccfc457c 100644 --- a/python/utils.py +++ b/python/utils.py @@ -625,6 +625,28 @@ or using the "mod_spatialite" extension (python3)""" return dbapi2.connect(*args, **kwargs) +class OverrideCursor(): + """ + Executes a code block with a different cursor set and makes sure the cursor + is restored even if exceptions are raised or an intermediate ``return`` + statement is hit. + + Example: + ``` + with OverrideCursor(Qt.WaitCursor): + do_a_slow(operation) + ``` + """ + + def __init__(self, cursor): + self.cursor = cursor + + def __enter__(self): + QApplication.setOverrideCursor(self.cursor) + + def __exit__(self, exc_type, exc_val, exc_tb): + QApplication.restoreOverrideCursor() + ####################### # IMPORT wrapper From 4b6b8434f4cefdb3db86bcb430fc6df4a32d4943 Mon Sep 17 00:00:00 2001 From: Matthias Kuhn Date: Sun, 30 Jul 2017 21:53:41 +0200 Subject: [PATCH 2/7] Avoid endless wait cursors in console --- python/console/console_editor.py | 22 +++++++++---------- .../processing/gui/GetScriptsAndModels.py | 2 +- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/python/console/console_editor.py b/python/console/console_editor.py index 5acb97dcd40..b99910cd518 100644 --- a/python/console/console_editor.py +++ b/python/console/console_editor.py @@ -27,6 +27,7 @@ from qgis.PyQt.QtWidgets import QShortcut, QMenu, QApplication, QWidget, QGridLa from qgis.PyQt.Qsci import QsciScintilla, QsciLexerPython, QsciAPIs, QsciStyle from qgis.core import QgsApplication, QgsSettings from qgis.gui import QgsMessageBar +from qgis.utils import OverrideCursor import sys import os import subprocess @@ -726,10 +727,9 @@ class Editor(QsciScintilla): file = open(pathfile, "r") fileLines = file.readlines() file.close() - QApplication.setOverrideCursor(Qt.WaitCursor) - for line in reversed(fileLines): - self.insert(line) - QApplication.restoreOverrideCursor() + with OverrideCursor(Qt.WaitCursor): + for line in reversed(fileLines): + self.insert(line) self.setModified(False) self.endUndoAction() @@ -785,11 +785,10 @@ class EditorTab(QWidget): fn = codecs.open(filename, "rb", encoding='utf-8') txt = fn.read() fn.close() - QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) - self.newEditor.setText(txt) - if self.readOnly: - self.newEditor.setReadOnly(self.readOnly) - QApplication.restoreOverrideCursor() + with OverrideCursor(Qt.WaitCursor): + self.newEditor.setText(txt) + if self.readOnly: + self.newEditor.setReadOnly(self.readOnly) self.newEditor.setModified(modified) self.newEditor.recolor() @@ -1259,9 +1258,8 @@ class EditorTabWidget(QTabWidget): if objInspectorEnabled: cW = self.currentWidget() if cW and not self.parent.listClassMethod.isVisible(): - QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) - self.listObject(cW) - QApplication.restoreOverrideCursor() + with OverrideCursor(Qt.WaitCursor): + self.listObject(cW) def changeLastDirPath(self, tab): tabWidget = self.widget(tab) diff --git a/python/plugins/processing/gui/GetScriptsAndModels.py b/python/plugins/processing/gui/GetScriptsAndModels.py index 8b917e3b5f9..5f546f96666 100644 --- a/python/plugins/processing/gui/GetScriptsAndModels.py +++ b/python/plugins/processing/gui/GetScriptsAndModels.py @@ -165,7 +165,7 @@ class GetScriptsAndModelsDialog(BASE, WIDGET): def grabHTTP(self, url, loadFunction, arguments=None): """Grab distant content via QGIS internal classes and QtNetwork.""" - QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) + QApplication.setOverrideCursor(Qt.WaitCursor) request = QUrl(url) reply = self.manager.get(QNetworkRequest(request)) if arguments: From 8473df562f1b29d17ffab6496ac5030e1793f3fe Mon Sep 17 00:00:00 2001 From: Matthias Kuhn Date: Sun, 30 Jul 2017 22:18:25 +0200 Subject: [PATCH 3/7] More endless hourglass protection --- .../db_manager/dlg_add_geometry_column.py | 15 +- .../db_manager/dlg_create_constraint.py | 15 +- python/plugins/db_manager/dlg_create_index.py | 15 +- .../plugins/db_manager/dlg_export_vector.py | 72 +++++----- .../plugins/db_manager/dlg_import_vector.py | 128 ++++++++--------- .../db_manager/dlg_sql_layer_window.py | 135 ++++++++---------- python/plugins/db_manager/dlg_sql_window.py | 131 ++++++++--------- .../db_manager/dlg_table_properties.py | 106 ++++++-------- python/plugins/db_manager/info_viewer.py | 16 +-- python/plugins/db_manager/layer_preview.py | 73 +++++----- python/plugins/db_manager/table_viewer.py | 24 ++-- 11 files changed, 340 insertions(+), 390 deletions(-) diff --git a/python/plugins/db_manager/dlg_add_geometry_column.py b/python/plugins/db_manager/dlg_add_geometry_column.py index 4dd2e57956f..ad54c1d06ed 100644 --- a/python/plugins/db_manager/dlg_add_geometry_column.py +++ b/python/plugins/db_manager/dlg_add_geometry_column.py @@ -24,6 +24,7 @@ The content of this file is based on from qgis.PyQt.QtCore import Qt from qgis.PyQt.QtWidgets import QDialog, QMessageBox, QApplication +from qgis.utils import OverrideCursor from .db_plugins.plugin import DbError from .dlg_db_error import DlgDbError @@ -59,13 +60,11 @@ class DlgAddGeometryColumn(QDialog, Ui_Dialog): createSpatialIndex = False # now create the geometry column - QApplication.setOverrideCursor(Qt.WaitCursor) - try: - self.table.addGeometryColumn(name, geom_type, srid, dim, createSpatialIndex) - except DbError as e: - DlgDbError.showError(e, self) - return - finally: - QApplication.restoreOverrideCursor() + with OverrideCursor(Qt.WaitCursor): + try: + self.table.addGeometryColumn(name, geom_type, srid, dim, createSpatialIndex) + except DbError as e: + DlgDbError.showError(e, self) + return self.accept() diff --git a/python/plugins/db_manager/dlg_create_constraint.py b/python/plugins/db_manager/dlg_create_constraint.py index 440973b2f20..614254ede7b 100644 --- a/python/plugins/db_manager/dlg_create_constraint.py +++ b/python/plugins/db_manager/dlg_create_constraint.py @@ -24,6 +24,7 @@ The content of this file is based on from qgis.PyQt.QtCore import Qt from qgis.PyQt.QtWidgets import QDialog, QApplication +from qgis.utils import OverrideCursor from .db_plugins.plugin import DbError from .dlg_db_error import DlgDbError @@ -52,14 +53,12 @@ class DlgCreateConstraint(QDialog, Ui_Dialog): constr = self.getConstraint() # now create the constraint - QApplication.setOverrideCursor(Qt.WaitCursor) - try: - self.table.addConstraint(constr) - except DbError as e: - DlgDbError.showError(e, self) - return - finally: - QApplication.restoreOverrideCursor() + with OverrideCursor(Qt.WaitCursor): + try: + self.table.addConstraint(constr) + except DbError as e: + DlgDbError.showError(e, self) + return self.accept() diff --git a/python/plugins/db_manager/dlg_create_index.py b/python/plugins/db_manager/dlg_create_index.py index f8495a97392..d4d9ac5c9ea 100644 --- a/python/plugins/db_manager/dlg_create_index.py +++ b/python/plugins/db_manager/dlg_create_index.py @@ -24,6 +24,7 @@ The content of this file is based on from qgis.PyQt.QtCore import Qt from qgis.PyQt.QtWidgets import QDialog, QMessageBox, QApplication +from qgis.utils import OverrideCursor from .db_plugins.plugin import DbError from .dlg_db_error import DlgDbError @@ -60,14 +61,12 @@ class DlgCreateIndex(QDialog, Ui_Dialog): return # now create the index - QApplication.setOverrideCursor(Qt.WaitCursor) - try: - self.table.addIndex(idx) - except DbError as e: - DlgDbError.showError(e, self) - return - finally: - QApplication.restoreOverrideCursor() + with OverrideCursor(Qt.WaitCursor): + try: + self.table.addIndex(idx) + except DbError as e: + DlgDbError.showError(e, self) + return self.accept() diff --git a/python/plugins/db_manager/dlg_export_vector.py b/python/plugins/db_manager/dlg_export_vector.py index 58adf362bd1..029efa45719 100644 --- a/python/plugins/db_manager/dlg_export_vector.py +++ b/python/plugins/db_manager/dlg_export_vector.py @@ -32,6 +32,7 @@ from qgis.core import (QgsVectorFileWriter, QgsCoordinateReferenceSystem, QgsVectorLayerExporter, QgsSettings) +from qgis.utils import OverrideCursor from .ui.ui_DlgExportVector import Ui_DbManagerDlgExportVector as Ui_Dialog @@ -145,51 +146,48 @@ class DlgExportVector(QDialog, Ui_Dialog): self.tr("Invalid target srid: must be an integer")) return - # override cursor - QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) - # store current input layer crs, so I can restore it later - prevInCrs = self.inLayer.crs() - try: - uri = self.editOutputFile.text() - providerName = "ogr" + with OverrideCursor(Qt.WaitCursor): + # store current input layer crs, so I can restore it later + prevInCrs = self.inLayer.crs() + try: + uri = self.editOutputFile.text() + providerName = "ogr" - options = {} + options = {} - # set the OGR driver will be used - driverName = self.cboFileFormat.currentData() - options['driverName'] = driverName + # set the OGR driver will be used + driverName = self.cboFileFormat.currentData() + options['driverName'] = driverName - # set the output file encoding - if self.chkEncoding.isEnabled() and self.chkEncoding.isChecked(): - enc = self.cboEncoding.currentText() - options['fileEncoding'] = enc + # set the output file encoding + if self.chkEncoding.isEnabled() and self.chkEncoding.isChecked(): + enc = self.cboEncoding.currentText() + options['fileEncoding'] = enc - if self.chkDropTable.isChecked(): - options['overwrite'] = True + if self.chkDropTable.isChecked(): + options['overwrite'] = True - outCrs = QgsCoordinateReferenceSystem() - if self.chkTargetSrid.isEnabled() and self.chkTargetSrid.isChecked(): - targetSrid = int(self.editTargetSrid.text()) - outCrs = QgsCoordinateReferenceSystem(targetSrid) + outCrs = QgsCoordinateReferenceSystem() + if self.chkTargetSrid.isEnabled() and self.chkTargetSrid.isChecked(): + targetSrid = int(self.editTargetSrid.text()) + outCrs = QgsCoordinateReferenceSystem(targetSrid) - # update input layer crs - if self.chkSourceSrid.isEnabled() and self.chkSourceSrid.isChecked(): - sourceSrid = int(self.editSourceSrid.text()) - inCrs = QgsCoordinateReferenceSystem(sourceSrid) - self.inLayer.setCrs(inCrs) + # update input layer crs + if self.chkSourceSrid.isEnabled() and self.chkSourceSrid.isChecked(): + sourceSrid = int(self.editSourceSrid.text()) + inCrs = QgsCoordinateReferenceSystem(sourceSrid) + self.inLayer.setCrs(inCrs) - # do the export! - ret, errMsg = QgsVectorLayerExporter.exportLayer(self.inLayer, uri, providerName, outCrs, - False, options) - except Exception as e: - ret = -1 - errMsg = str(e) + # do the export! + ret, errMsg = QgsVectorLayerExporter.exportLayer(self.inLayer, uri, providerName, outCrs, + False, options) + except Exception as e: + ret = -1 + errMsg = str(e) - finally: - # restore input layer crs and encoding - self.inLayer.setCrs(prevInCrs) - # restore cursor - QApplication.restoreOverrideCursor() + finally: + # restore input layer crs and encoding + self.inLayer.setCrs(prevInCrs) if ret != 0: QMessageBox.warning(self, self.tr("Export to file"), self.tr("Error {0}\n{1}").format(ret, errMsg)) diff --git a/python/plugins/db_manager/dlg_import_vector.py b/python/plugins/db_manager/dlg_import_vector.py index 45da8284939..4eb187cfb47 100644 --- a/python/plugins/db_manager/dlg_import_vector.py +++ b/python/plugins/db_manager/dlg_import_vector.py @@ -37,6 +37,7 @@ from qgis.core import (QgsDataSourceUri, QgsProject, QgsSettings) from qgis.gui import QgsMessageViewer +from qgis.utils import OverrideCursor from .ui.ui_DlgImportVector import Ui_DbManagerDlgImportVector as Ui_Dialog @@ -292,85 +293,82 @@ class DlgImportVector(QDialog, Ui_Dialog): self.tr("Invalid target srid: must be an integer")) return - # override cursor - QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) - # store current input layer crs and encoding, so I can restore it - prevInCrs = self.inLayer.crs() - prevInEncoding = self.inLayer.dataProvider().encoding() + with OverrideCursor(Qt.WaitCursor): + # store current input layer crs and encoding, so I can restore it + prevInCrs = self.inLayer.crs() + prevInEncoding = self.inLayer.dataProvider().encoding() - try: - schema = self.outUri.schema() if not self.cboSchema.isEnabled() else self.cboSchema.currentText() - table = self.cboTable.currentText() + try: + schema = self.outUri.schema() if not self.cboSchema.isEnabled() else self.cboSchema.currentText() + table = self.cboTable.currentText() - # get pk and geom field names from the source layer or use the - # ones defined by the user - srcUri = QgsDataSourceUri(self.inLayer.source()) + # get pk and geom field names from the source layer or use the + # ones defined by the user + srcUri = QgsDataSourceUri(self.inLayer.source()) - pk = srcUri.keyColumn() if not self.chkPrimaryKey.isChecked() else self.editPrimaryKey.text() - if not pk: - pk = self.default_pk + pk = srcUri.keyColumn() if not self.chkPrimaryKey.isChecked() else self.editPrimaryKey.text() + if not pk: + pk = self.default_pk - if self.inLayer.isSpatial() and self.chkGeomColumn.isEnabled(): - geom = srcUri.geometryColumn() if not self.chkGeomColumn.isChecked() else self.editGeomColumn.text() - if not geom: - geom = self.default_geom - else: - geom = None + if self.inLayer.isSpatial() and self.chkGeomColumn.isEnabled(): + geom = srcUri.geometryColumn() if not self.chkGeomColumn.isChecked() else self.editGeomColumn.text() + if not geom: + geom = self.default_geom + else: + geom = None - options = {} - if self.chkLowercaseFieldNames.isEnabled() and self.chkLowercaseFieldNames.isChecked(): - pk = pk.lower() - if geom: - geom = geom.lower() - options['lowercaseFieldNames'] = True + options = {} + if self.chkLowercaseFieldNames.isEnabled() and self.chkLowercaseFieldNames.isChecked(): + pk = pk.lower() + if geom: + geom = geom.lower() + options['lowercaseFieldNames'] = True - # get output params, update output URI - self.outUri.setDataSource(schema, table, geom, "", pk) - typeName = self.db.dbplugin().typeName() - providerName = self.db.dbplugin().providerName() - if typeName == 'gpkg': - uri = self.outUri.database() - options['update'] = True - options['driverName'] = 'GPKG' - options['layerName'] = table - else: - uri = self.outUri.uri(False) + # get output params, update output URI + self.outUri.setDataSource(schema, table, geom, "", pk) + typeName = self.db.dbplugin().typeName() + providerName = self.db.dbplugin().providerName() + if typeName == 'gpkg': + uri = self.outUri.database() + options['update'] = True + options['driverName'] = 'GPKG' + options['layerName'] = table + else: + uri = self.outUri.uri(False) - if self.chkDropTable.isChecked(): - options['overwrite'] = True + if self.chkDropTable.isChecked(): + options['overwrite'] = True - if self.chkSinglePart.isEnabled() and self.chkSinglePart.isChecked(): - options['forceSinglePartGeometryType'] = True + if self.chkSinglePart.isEnabled() and self.chkSinglePart.isChecked(): + options['forceSinglePartGeometryType'] = True - outCrs = QgsCoordinateReferenceSystem() - if self.chkTargetSrid.isEnabled() and self.chkTargetSrid.isChecked(): - targetSrid = int(self.editTargetSrid.text()) - outCrs = QgsCoordinateReferenceSystem(targetSrid) + outCrs = QgsCoordinateReferenceSystem() + if self.chkTargetSrid.isEnabled() and self.chkTargetSrid.isChecked(): + targetSrid = int(self.editTargetSrid.text()) + outCrs = QgsCoordinateReferenceSystem(targetSrid) - # update input layer crs and encoding - if self.chkSourceSrid.isEnabled() and self.chkSourceSrid.isChecked(): - sourceSrid = int(self.editSourceSrid.text()) - inCrs = QgsCoordinateReferenceSystem(sourceSrid) - self.inLayer.setCrs(inCrs) + # update input layer crs and encoding + if self.chkSourceSrid.isEnabled() and self.chkSourceSrid.isChecked(): + sourceSrid = int(self.editSourceSrid.text()) + inCrs = QgsCoordinateReferenceSystem(sourceSrid) + self.inLayer.setCrs(inCrs) - if self.chkEncoding.isEnabled() and self.chkEncoding.isChecked(): - enc = self.cboEncoding.currentText() - self.inLayer.setProviderEncoding(enc) + if self.chkEncoding.isEnabled() and self.chkEncoding.isChecked(): + enc = self.cboEncoding.currentText() + self.inLayer.setProviderEncoding(enc) - onlySelected = self.chkSelectedFeatures.isChecked() + onlySelected = self.chkSelectedFeatures.isChecked() - # do the import! - ret, errMsg = QgsVectorLayerExporter.exportLayer(self.inLayer, uri, providerName, outCrs, onlySelected, options) - except Exception as e: - ret = -1 - errMsg = str(e) + # do the import! + ret, errMsg = QgsVectorLayerExporter.exportLayer(self.inLayer, uri, providerName, outCrs, onlySelected, options) + except Exception as e: + ret = -1 + errMsg = str(e) - finally: - # restore input layer crs and encoding - self.inLayer.setCrs(prevInCrs) - self.inLayer.setProviderEncoding(prevInEncoding) - # restore cursor - QApplication.restoreOverrideCursor() + finally: + # restore input layer crs and encoding + self.inLayer.setCrs(prevInCrs) + self.inLayer.setProviderEncoding(prevInEncoding) if ret != 0: output = QgsMessageViewer() diff --git a/python/plugins/db_manager/dlg_sql_layer_window.py b/python/plugins/db_manager/dlg_sql_layer_window.py index 40422dafe41..f606441cfb2 100644 --- a/python/plugins/db_manager/dlg_sql_layer_window.py +++ b/python/plugins/db_manager/dlg_sql_layer_window.py @@ -32,6 +32,7 @@ from qgis.PyQt.Qsci import QsciAPIs from qgis.PyQt.QtXml import QDomDocument from qgis.core import QgsProject, QgsDataSourceUri +from qgis.utils import OverrideCursor from .db_plugins import createDbPlugin from .db_plugins.plugin import BaseError @@ -223,37 +224,35 @@ class DlgSqlLayerWindow(QWidget, Ui_Dialog): if sql == "": return - QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) + with OverrideCursor(Qt.WaitCursor): - # delete the old model - old_model = self.viewResult.model() - self.viewResult.setModel(None) - if old_model: - old_model.deleteLater() + # delete the old model + old_model = self.viewResult.model() + self.viewResult.setModel(None) + if old_model: + old_model.deleteLater() - cols = [] - quotedCols = [] + cols = [] + quotedCols = [] - try: - # set the new model - model = self.db.sqlResultModel(sql, self) - self.viewResult.setModel(model) - self.lblResult.setText(self.tr("{0} rows, {1:.1f} seconds").format(model.affectedRows(), model.secs())) - cols = self.viewResult.model().columnNames() - for col in cols: - quotedCols.append(self.db.connector.quoteId(col)) + try: + # set the new model + model = self.db.sqlResultModel(sql, self) + self.viewResult.setModel(model) + self.lblResult.setText(self.tr("{0} rows, {1:.1f} seconds").format(model.affectedRows(), model.secs())) + cols = self.viewResult.model().columnNames() + for col in cols: + quotedCols.append(self.db.connector.quoteId(col)) - except BaseError as e: - QApplication.restoreOverrideCursor() - DlgDbError.showError(e, self) - self.uniqueModel.clear() - self.geomCombo.clear() - return + except BaseError as e: + DlgDbError.showError(e, self) + self.uniqueModel.clear() + self.geomCombo.clear() + return - self.setColumnCombos(cols, quotedCols) + self.setColumnCombos(cols, quotedCols) - self.update() - QApplication.restoreOverrideCursor() + self.update() def _getSqlLayer(self, _filter): hasUniqueField = self.uniqueColumnCheck.checkState() == Qt.Checked @@ -311,19 +310,15 @@ class DlgSqlLayerWindow(QWidget, Ui_Dialog): return None def loadSqlLayer(self): - QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) - try: + with OverrideCursor(Qt.WaitCursor): layer = self._getSqlLayer(self.filter) if layer is None: return QgsProject.instance().addMapLayers([layer], True) - finally: - QApplication.restoreOverrideCursor() def updateSqlLayer(self): - QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) - try: + with OverrideCursor(Qt.WaitCursor): layer = self._getSqlLayer(self.filter) if layer is None: return @@ -341,60 +336,54 @@ class DlgSqlLayerWindow(QWidget, Ui_Dialog): self.layer.reload() self.iface.actionDraw().trigger() self.iface.mapCanvas().refresh() - finally: - QApplication.restoreOverrideCursor() def fillColumnCombos(self): query = self._getSqlQuery() if query == "": return - QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) + with OverrideCursor(Qt.WaitCursor): + # remove a trailing ';' from query if present + if query.strip().endswith(';'): + query = query.strip()[:-1] - # remove a trailing ';' from query if present - if query.strip().endswith(';'): - query = query.strip()[:-1] + # get all the columns + cols = [] + quotedCols = [] + connector = self.db.connector + if self.aliasSubQuery: + # get a new alias + aliasIndex = 0 + while True: + alias = "_subQuery__%d" % aliasIndex + escaped = re.compile('\\b("?)' + re.escape(alias) + '\\1\\b') + if not escaped.search(query): + break + aliasIndex += 1 - # get all the columns - cols = [] - quotedCols = [] - connector = self.db.connector - if self.aliasSubQuery: - # get a new alias - aliasIndex = 0 - while True: - alias = "_subQuery__%d" % aliasIndex - escaped = re.compile('\\b("?)' + re.escape(alias) + '\\1\\b') - if not escaped.search(query): - break - aliasIndex += 1 + sql = u"SELECT * FROM (%s\n) AS %s LIMIT 0" % (str(query), connector.quoteId(alias)) + else: + sql = u"SELECT * FROM (%s\n) WHERE 1=0" % str(query) - sql = u"SELECT * FROM (%s\n) AS %s LIMIT 0" % (str(query), connector.quoteId(alias)) - else: - sql = u"SELECT * FROM (%s\n) WHERE 1=0" % str(query) + c = None + try: + c = connector._execute(None, sql) + cols = connector._get_cursor_columns(c) + for col in cols: + quotedCols.append(connector.quoteId(col)) - c = None - try: - c = connector._execute(None, sql) - cols = connector._get_cursor_columns(c) - for col in cols: - quotedCols.append(connector.quoteId(col)) + except BaseError as e: + DlgDbError.showError(e, self) + self.uniqueModel.clear() + self.geomCombo.clear() + return - except BaseError as e: - QApplication.restoreOverrideCursor() - DlgDbError.showError(e, self) - self.uniqueModel.clear() - self.geomCombo.clear() - return + finally: + if c: + c.close() + del c - finally: - if c: - c.close() - del c - - self.setColumnCombos(cols, quotedCols) - - QApplication.restoreOverrideCursor() + self.setColumnCombos(cols, quotedCols) def setColumnCombos(self, cols, quotedCols): # get sensible default columns. do this before sorting in case there's hints in the column order (e.g., id is more likely to be first) diff --git a/python/plugins/db_manager/dlg_sql_window.py b/python/plugins/db_manager/dlg_sql_window.py index 19d22e69cae..e8f8415abd9 100644 --- a/python/plugins/db_manager/dlg_sql_window.py +++ b/python/plugins/db_manager/dlg_sql_window.py @@ -31,6 +31,7 @@ from qgis.PyQt.QtGui import QKeySequence, QCursor, QClipboard, QIcon, QStandardI from qgis.PyQt.Qsci import QsciAPIs from qgis.core import QgsProject +from qgis.utils import OverrideCursor from .db_plugins.plugin import BaseError from .db_plugins.postgis.plugin import PGDatabase @@ -182,37 +183,34 @@ class DlgSqlWindow(QWidget, Ui_Dialog): if sql == "": return - QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) + with OverrideCursor(Qt.WaitCursor): + # delete the old model + old_model = self.viewResult.model() + self.viewResult.setModel(None) + if old_model: + old_model.deleteLater() - # delete the old model - old_model = self.viewResult.model() - self.viewResult.setModel(None) - if old_model: - old_model.deleteLater() + cols = [] + quotedCols = [] - cols = [] - quotedCols = [] + try: + # set the new model + model = self.db.sqlResultModel(sql, self) + self.viewResult.setModel(model) + self.lblResult.setText(self.tr("{0} rows, {1:.1f} seconds").format(model.affectedRows(), model.secs())) + cols = self.viewResult.model().columnNames() + for col in cols: + quotedCols.append(self.db.connector.quoteId(col)) - try: - # set the new model - model = self.db.sqlResultModel(sql, self) - self.viewResult.setModel(model) - self.lblResult.setText(self.tr("{0} rows, {1:.1f} seconds").format(model.affectedRows(), model.secs())) - cols = self.viewResult.model().columnNames() - for col in cols: - quotedCols.append(self.db.connector.quoteId(col)) + except BaseError as e: + DlgDbError.showError(e, self) + self.uniqueModel.clear() + self.geomCombo.clear() + return - except BaseError as e: - QApplication.restoreOverrideCursor() - DlgDbError.showError(e, self) - self.uniqueModel.clear() - self.geomCombo.clear() - return + self.setColumnCombos(cols, quotedCols) - self.setColumnCombos(cols, quotedCols) - - self.update() - QApplication.restoreOverrideCursor() + self.update() def _getSqlLayer(self, _filter): hasUniqueField = self.uniqueColumnCheck.checkState() == Qt.Checked @@ -270,67 +268,60 @@ class DlgSqlWindow(QWidget, Ui_Dialog): return None def loadSqlLayer(self): - QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) - try: + with OverrideCursor(Qt.WaitCursor): layer = self._getSqlLayer(self.filter) if layer is None: return QgsProject.instance().addMapLayers([layer], True) - finally: - QApplication.restoreOverrideCursor() def fillColumnCombos(self): query = self._getSqlQuery() if query == "": return - QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) + with OverrideCursor(Qt.WaitCursor): + # remove a trailing ';' from query if present + if query.strip().endswith(';'): + query = query.strip()[:-1] - # remove a trailing ';' from query if present - if query.strip().endswith(';'): - query = query.strip()[:-1] + # get all the columns + cols = [] + quotedCols = [] + connector = self.db.connector + if self.aliasSubQuery: + # get a new alias + aliasIndex = 0 + while True: + alias = "_subQuery__%d" % aliasIndex + escaped = re.compile('\\b("?)' + re.escape(alias) + '\\1\\b') + if not escaped.search(query): + break + aliasIndex += 1 - # get all the columns - cols = [] - quotedCols = [] - connector = self.db.connector - if self.aliasSubQuery: - # get a new alias - aliasIndex = 0 - while True: - alias = "_subQuery__%d" % aliasIndex - escaped = re.compile('\\b("?)' + re.escape(alias) + '\\1\\b') - if not escaped.search(query): - break - aliasIndex += 1 + sql = u"SELECT * FROM (%s\n) AS %s LIMIT 0" % (str(query), connector.quoteId(alias)) + else: + sql = u"SELECT * FROM (%s\n) WHERE 1=0" % str(query) - sql = u"SELECT * FROM (%s\n) AS %s LIMIT 0" % (str(query), connector.quoteId(alias)) - else: - sql = u"SELECT * FROM (%s\n) WHERE 1=0" % str(query) + c = None + try: + c = connector._execute(None, sql) + cols = connector._get_cursor_columns(c) + for col in cols: + quotedCols.append(connector.quoteId(col)) - c = None - try: - c = connector._execute(None, sql) - cols = connector._get_cursor_columns(c) - for col in cols: - quotedCols.append(connector.quoteId(col)) + except BaseError as e: + DlgDbError.showError(e, self) + self.uniqueModel.clear() + self.geomCombo.clear() + return - except BaseError as e: - QApplication.restoreOverrideCursor() - DlgDbError.showError(e, self) - self.uniqueModel.clear() - self.geomCombo.clear() - return + finally: + if c: + c.close() + del c - finally: - if c: - c.close() - del c - - self.setColumnCombos(cols, quotedCols) - - QApplication.restoreOverrideCursor() + self.setColumnCombos(cols, quotedCols) def setColumnCombos(self, cols, quotedCols): # get sensible default columns. do this before sorting in case there's hints in the column order (e.g., id is more likely to be first) diff --git a/python/plugins/db_manager/dlg_table_properties.py b/python/plugins/db_manager/dlg_table_properties.py index cf66b1b7091..58fe6c83c85 100644 --- a/python/plugins/db_manager/dlg_table_properties.py +++ b/python/plugins/db_manager/dlg_table_properties.py @@ -26,6 +26,8 @@ from builtins import range from qgis.PyQt.QtCore import Qt, pyqtSignal from qgis.PyQt.QtWidgets import QDialog, QMessageBox, QApplication +from qgis.utils import OverrideCursor + from .db_plugins.data_model import TableFieldsModel, TableConstraintsModel, TableIndexesModel from .db_plugins.plugin import BaseError from .dlg_db_error import DlgDbError @@ -116,17 +118,14 @@ class DlgTableProperties(QDialog, Ui_Dialog): return fld = dlg.getField() - QApplication.setOverrideCursor(Qt.WaitCursor) - self.aboutToChangeTable.emit() - try: - # add column to table - self.table.addField(fld) - self.refresh() - except BaseError as e: - DlgDbError.showError(e, self) - return - finally: - QApplication.restoreOverrideCursor() + with OverrideCursor(Qt.WaitCursor): + self.aboutToChangeTable.emit() + try: + # add column to table + self.table.addField(fld) + self.refresh() + except BaseError as e: + DlgDbError.showError(e, self) def addGeometryColumn(self): """ open dialog to add geometry column """ @@ -151,16 +150,13 @@ class DlgTableProperties(QDialog, Ui_Dialog): return new_fld = dlg.getField(True) - QApplication.setOverrideCursor(Qt.WaitCursor) - self.aboutToChangeTable.emit() - try: - fld.update(new_fld.name, new_fld.type2String(), new_fld.notNull, new_fld.default2String()) - self.refresh() - except BaseError as e: - DlgDbError.showError(e, self) - return - finally: - QApplication.restoreOverrideCursor() + with OverrideCursor(Qt.WaitCursor): + self.aboutToChangeTable.emit() + try: + fld.update(new_fld.name, new_fld.type2String(), new_fld.notNull, new_fld.default2String()) + self.refresh() + except BaseError as e: + DlgDbError.showError(e, self) def deleteColumn(self): """ delete currently selected column """ @@ -176,16 +172,13 @@ class DlgTableProperties(QDialog, Ui_Dialog): if res != QMessageBox.Yes: return - QApplication.setOverrideCursor(Qt.WaitCursor) - self.aboutToChangeTable.emit() - try: - fld.delete() - self.refresh() - except BaseError as e: - DlgDbError.showError(e, self) - return - finally: - QApplication.restoreOverrideCursor() + with OverrideCursor(Qt.WaitCursor): + self.aboutToChangeTable.emit() + try: + fld.delete() + self.refresh() + except BaseError as e: + DlgDbError.showError(e, self) def populateConstraints(self): constraints = self.table.constraints() @@ -231,16 +224,13 @@ class DlgTableProperties(QDialog, Ui_Dialog): if res != QMessageBox.Yes: return - QApplication.setOverrideCursor(Qt.WaitCursor) - self.aboutToChangeTable.emit() - try: - constr.delete() - self.refresh() - except BaseError as e: - DlgDbError.showError(e, self) - return - finally: - QApplication.restoreOverrideCursor() + with OverrideCursor(Qt.WaitCursor): + self.aboutToChangeTable.emit() + try: + constr.delete() + self.refresh() + except BaseError as e: + DlgDbError.showError(e, self) def currentConstraint(self): """ returns row index of selected index """ @@ -291,17 +281,14 @@ class DlgTableProperties(QDialog, Ui_Dialog): return # TODO: first check whether the index doesn't exist already - QApplication.setOverrideCursor(Qt.WaitCursor) - self.aboutToChangeTable.emit() + with OverrideCursor(Qt.WaitCursor): + self.aboutToChangeTable.emit() - try: - self.table.createSpatialIndex() - self.refresh() - except BaseError as e: - DlgDbError.showError(e, self) - return - finally: - QApplication.restoreOverrideCursor() + try: + self.table.createSpatialIndex() + self.refresh() + except BaseError as e: + DlgDbError.showError(e, self) def currentIndex(self): """ returns row index of selected index """ @@ -326,13 +313,10 @@ class DlgTableProperties(QDialog, Ui_Dialog): if res != QMessageBox.Yes: return - QApplication.setOverrideCursor(Qt.WaitCursor) - self.aboutToChangeTable.emit() - try: - idx.delete() - self.refresh() - except BaseError as e: - DlgDbError.showError(e, self) - return - finally: - QApplication.restoreOverrideCursor() + with OverrideCursor(Qt.WaitCursor): + self.aboutToChangeTable.emit() + try: + idx.delete() + self.refresh() + except BaseError as e: + DlgDbError.showError(e, self) diff --git a/python/plugins/db_manager/info_viewer.py b/python/plugins/db_manager/info_viewer.py index 7295663441f..bf1a7252a36 100644 --- a/python/plugins/db_manager/info_viewer.py +++ b/python/plugins/db_manager/info_viewer.py @@ -23,6 +23,7 @@ from builtins import str from qgis.PyQt.QtCore import Qt from qgis.PyQt.QtWidgets import QTextBrowser, QApplication +from qgis.utils import OverrideCursor from .db_plugins.plugin import BaseError, DbError, DBPlugin, Schema, Table from .dlg_db_error import DlgDbError @@ -47,15 +48,12 @@ class InfoViewer(QTextBrowser): return if url.scheme() == "action": - QApplication.setOverrideCursor(Qt.WaitCursor) - try: - if self.item.runAction(url.path()): - self.refresh() - except BaseError as e: - DlgDbError.showError(e, self) - return - finally: - QApplication.restoreOverrideCursor() + with OverrideCursor(Qt.WaitCursor): + try: + if self.item.runAction(url.path()): + self.refresh() + except BaseError as e: + DlgDbError.showError(e, self) def refresh(self): self.setDirty(True) diff --git a/python/plugins/db_manager/layer_preview.py b/python/plugins/db_manager/layer_preview.py index 7664d88fce1..17c5f39a400 100644 --- a/python/plugins/db_manager/layer_preview.py +++ b/python/plugins/db_manager/layer_preview.py @@ -89,45 +89,44 @@ class LayerPreview(QgsMapCanvas): def _loadTablePreview(self, table, limit=False): """ if has geometry column load to map canvas """ - QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) - self.freeze() - vl = None + with OverrideCursor(Qt.WaitCursor): + self.freeze() + vl = None - if table and table.geomType: - # limit the query result if required - if limit and table.rowCount > 1000: - uniqueField = table.getValidQgisUniqueFields(True) - if uniqueField is None: - self.parent.tabs.setCurrentWidget(self.parent.info) - self.parent.infoBar.pushMessage( - QApplication.translate("DBManagerPlugin", "Unable to find a valid unique field"), - QgsMessageBar.WARNING, self.parent.iface.messageTimeout()) - return + if table and table.geomType: + # limit the query result if required + if limit and table.rowCount > 1000: + uniqueField = table.getValidQgisUniqueFields(True) + if uniqueField is None: + self.parent.tabs.setCurrentWidget(self.parent.info) + self.parent.infoBar.pushMessage( + QApplication.translate("DBManagerPlugin", "Unable to find a valid unique field"), + QgsMessageBar.WARNING, self.parent.iface.messageTimeout()) + return - uri = table.database().uri() - uri.setDataSource("", u"(SELECT * FROM %s LIMIT 1000)" % table.quotedName(), table.geomColumn, "", - uniqueField.name) - provider = table.database().dbplugin().providerName() - vl = QgsVectorLayer(uri.uri(False), table.name, provider) + uri = table.database().uri() + uri.setDataSource("", u"(SELECT * FROM %s LIMIT 1000)" % table.quotedName(), table.geomColumn, "", + uniqueField.name) + provider = table.database().dbplugin().providerName() + vl = QgsVectorLayer(uri.uri(False), table.name, provider) + else: + vl = table.toMapLayer() + + if not vl.isValid(): + vl.deleteLater() + vl = None + + # remove old layer (if any) and set new + if self.currentLayer: + QgsProject.instance().removeMapLayers([self.currentLayer.id()]) + + if vl: + self.setLayers([vl]) + QgsProject.instance().addMapLayers([vl], False) + self.zoomToFullExtent() else: - vl = table.toMapLayer() + self.setLayers([]) - if not vl.isValid(): - vl.deleteLater() - vl = None + self.currentLayer = vl - # remove old layer (if any) and set new - if self.currentLayer: - QgsProject.instance().removeMapLayers([self.currentLayer.id()]) - - if vl: - self.setLayers([vl]) - QgsProject.instance().addMapLayers([vl], False) - self.zoomToFullExtent() - else: - self.setLayers([]) - - self.currentLayer = vl - - self.freeze(False) - QApplication.restoreOverrideCursor() + self.freeze(False) diff --git a/python/plugins/db_manager/table_viewer.py b/python/plugins/db_manager/table_viewer.py index 6cd10b934c3..41cf303653d 100644 --- a/python/plugins/db_manager/table_viewer.py +++ b/python/plugins/db_manager/table_viewer.py @@ -24,6 +24,8 @@ from qgis.PyQt.QtCore import Qt from qgis.PyQt.QtWidgets import QTableView, QAbstractItemView, QApplication, QAction from qgis.PyQt.QtGui import QKeySequence, QCursor, QClipboard +from qgis.utils import OverrideCursor + from .db_plugins.plugin import DbError, Table from .dlg_db_error import DlgDbError @@ -86,20 +88,14 @@ class TableViewer(QTableView): model.deleteLater() def _loadTableData(self, table): - QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) - try: - # set the new model - self.setModel(table.tableDataModel(self)) - - except DbError as e: - DlgDbError.showError(e, self) - return - - else: - self.update() - - finally: - QApplication.restoreOverrideCursor() + with OverrideCursor(Qt.WaitCursor): + try: + # set the new model + self.setModel(table.tableDataModel(self)) + except DbError as e: + DlgDbError.showError(e, self) + else: + self.update() def copySelectedResults(self): if len(self.selectedIndexes()) <= 0: From 3ce6fcd31d8cbf1b28279f60dacfd3ccc238eee2 Mon Sep 17 00:00:00 2001 From: Matthias Kuhn Date: Sun, 30 Jul 2017 22:36:51 +0200 Subject: [PATCH 4/7] Even more endless hourglass avoidance --- python/plugins/db_manager/db_model.py | 57 +++++++++---------- python/plugins/db_manager/dlg_create_table.py | 21 +++---- .../processing/gui/ScriptEditorDialog.py | 17 +++--- 3 files changed, 43 insertions(+), 52 deletions(-) diff --git a/python/plugins/db_manager/db_model.py b/python/plugins/db_manager/db_model.py index 4ee0f4d2284..0650791f480 100644 --- a/python/plugins/db_manager/db_model.py +++ b/python/plugins/db_manager/db_model.py @@ -32,6 +32,7 @@ from .db_plugins.plugin import BaseError, Table, Database from .dlg_db_error import DlgDbError from qgis.core import QgsDataSourceUri, QgsVectorLayer, QgsRasterLayer, QgsMimeDataUtils +from qgis.utils import OverrideCursor from . import resources_rc # NOQA @@ -458,17 +459,15 @@ class DBModel(QAbstractItemModel): if new_value == obj.name: return False - QApplication.setOverrideCursor(Qt.WaitCursor) - try: - obj.rename(new_value) - self._onDataChanged(index) - except BaseError as e: - DlgDbError.showError(e, self.treeView) - return False - finally: - QApplication.restoreOverrideCursor() - - return True + with OverrideCursor(Qt.WaitCursor): + try: + obj.rename(new_value) + self._onDataChanged(index) + except BaseError as e: + DlgDbError.showError(e, self.treeView) + return False + else: + return True return False @@ -480,27 +479,23 @@ class DBModel(QAbstractItemModel): self.endRemoveRows() def _refreshIndex(self, index, force=False): - QApplication.setOverrideCursor(Qt.WaitCursor) - try: - item = index.internalPointer() if index.isValid() else self.rootItem - prevPopulated = item.populated - if prevPopulated: - self.removeRows(0, self.rowCount(index), index) + with OverrideCursor(Qt.WaitCursor): + try: + item = index.internalPointer() if index.isValid() else self.rootItem + prevPopulated = item.populated + if prevPopulated: + self.removeRows(0, self.rowCount(index), index) + item.populated = False + if prevPopulated or force: + if item.populate(): + for child in item.childItems: + child.changed.connect(partial(self.refreshItem, child)) + self._onDataChanged(index) + else: + self.notPopulated.emit(index) + + except BaseError: item.populated = False - if prevPopulated or force: - if item.populate(): - for child in item.childItems: - child.changed.connect(partial(self.refreshItem, child)) - self._onDataChanged(index) - else: - self.notPopulated.emit(index) - - except BaseError: - item.populated = False - return - - finally: - QApplication.restoreOverrideCursor() def _onDataChanged(self, indexFrom, indexTo=None): if indexTo is None: diff --git a/python/plugins/db_manager/dlg_create_table.py b/python/plugins/db_manager/dlg_create_table.py index 0e76e7416ef..4508736a0e1 100644 --- a/python/plugins/db_manager/dlg_create_table.py +++ b/python/plugins/db_manager/dlg_create_table.py @@ -297,19 +297,16 @@ class DlgCreateTable(QDialog, Ui_Dialog): flds[pk_index].primaryKey = True # commit to DB - QApplication.setOverrideCursor(Qt.WaitCursor) - try: - if not useGeomColumn: - self.db.createTable(table, flds, schema) - else: - geom = geomColumn, geomType, geomSrid, geomDim, useSpatialIndex - self.db.createVectorTable(table, flds, geom, schema) + with OverrideCursor(Qt.WaitCursor): + try: + if not useGeomColumn: + self.db.createTable(table, flds, schema) + else: + geom = geomColumn, geomType, geomSrid, geomDim, useSpatialIndex + self.db.createVectorTable(table, flds, geom, schema) - except (ConnectionError, DbError) as e: - DlgDbError.showError(e, self) + except (ConnectionError, DbError) as e: + DlgDbError.showError(e, self) return - finally: - QApplication.restoreOverrideCursor() - QMessageBox.information(self, self.tr("Good"), self.tr("everything went fine")) diff --git a/python/plugins/processing/gui/ScriptEditorDialog.py b/python/plugins/processing/gui/ScriptEditorDialog.py index cb2d85266fa..87b9f8db3a2 100644 --- a/python/plugins/processing/gui/ScriptEditorDialog.py +++ b/python/plugins/processing/gui/ScriptEditorDialog.py @@ -38,7 +38,7 @@ from qgis.PyQt.QtWidgets import (QMessageBox, QApplication) from qgis.core import QgsApplication, QgsSettings -from qgis.utils import iface +from qgis.utils import iface, OverrideCursor from processing.gui.AlgorithmDialog import AlgorithmDialog from processing.gui.HelpEditionDialog import HelpEditionDialog @@ -207,15 +207,14 @@ class ScriptEditorDialog(BASE, WIDGET): if self.filename == '': return - QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) - with codecs.open(self.filename, 'r', encoding='utf-8') as f: - txt = f.read() + with OverrideCursor(Qt.WaitCursor): + with codecs.open(self.filename, 'r', encoding='utf-8') as f: + txt = f.read() - self.editor.setText(txt) - self.hasChanged = False - self.editor.setModified(False) - self.editor.recolor() - QApplication.restoreOverrideCursor() + self.editor.setText(txt) + self.hasChanged = False + self.editor.setModified(False) + self.editor.recolor() def save(self): self.saveScript(False) From b262604f7aeaae8a1205f4ea9cc34081f72c9eea Mon Sep 17 00:00:00 2001 From: Matthias Kuhn Date: Sun, 30 Jul 2017 22:42:57 +0200 Subject: [PATCH 5/7] Add missing import --- python/plugins/db_manager/dlg_create_table.py | 2 ++ python/plugins/db_manager/layer_preview.py | 1 + 2 files changed, 3 insertions(+) diff --git a/python/plugins/db_manager/dlg_create_table.py b/python/plugins/db_manager/dlg_create_table.py index 4508736a0e1..f18a4cd9592 100644 --- a/python/plugins/db_manager/dlg_create_table.py +++ b/python/plugins/db_manager/dlg_create_table.py @@ -28,6 +28,8 @@ from qgis.PyQt.QtCore import Qt, QModelIndex from qgis.PyQt.QtWidgets import QItemDelegate, QComboBox, QDialog, QPushButton, QDialogButtonBox, QMessageBox, QApplication from qgis.PyQt.QtCore import QItemSelectionModel, pyqtSignal +from qgis.utils import OverrideCursor + from .db_plugins.data_model import TableFieldsModel from .db_plugins.plugin import DbError, ConnectionError from .dlg_db_error import DlgDbError diff --git a/python/plugins/db_manager/layer_preview.py b/python/plugins/db_manager/layer_preview.py index 17c5f39a400..af9654c9d91 100644 --- a/python/plugins/db_manager/layer_preview.py +++ b/python/plugins/db_manager/layer_preview.py @@ -26,6 +26,7 @@ from qgis.PyQt.QtWidgets import QApplication from qgis.gui import QgsMapCanvas, QgsMessageBar from qgis.core import QgsVectorLayer, QgsProject, QgsSettings +from qgis.utils import OverrideCursor from .db_plugins.plugin import Table From 3dc6daaffa0f24756ff657f182817f238fbd3081 Mon Sep 17 00:00:00 2001 From: Matthias Kuhn Date: Mon, 31 Jul 2017 09:28:11 +0200 Subject: [PATCH 6/7] Fix typo --- .../plugins/processing/algs/qgis/ui/FieldsCalculatorDialog.py | 2 +- python/utils.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/python/plugins/processing/algs/qgis/ui/FieldsCalculatorDialog.py b/python/plugins/processing/algs/qgis/ui/FieldsCalculatorDialog.py index 275d5abb522..a43b3a4cb49 100644 --- a/python/plugins/processing/algs/qgis/ui/FieldsCalculatorDialog.py +++ b/python/plugins/processing/algs/qgis/ui/FieldsCalculatorDialog.py @@ -223,7 +223,7 @@ class FieldsCalculatorDialog(BASE, WIDGET): keepOpen = ProcessingConfig.getSetting(ProcessingConfig.KEEP_DIALOG_OPEN) parameters = self.getParamValues() if parameters: - with OverrideCusor(Qt.WaitCursor): + with OverrideCursor(Qt.WaitCursor): context = dataobjects.createContext() ProcessingLog.addToLog(self.alg.asPythonCommand(parameters, context)) diff --git a/python/utils.py b/python/utils.py index 205ccfc457c..48080bd1ad8 100644 --- a/python/utils.py +++ b/python/utils.py @@ -650,6 +650,7 @@ class OverrideCursor(): ####################### # IMPORT wrapper + _uses_builtins = True try: import builtins From 1da9c607c951bab864245adbaae8f665111088e7 Mon Sep 17 00:00:00 2001 From: Matthias Kuhn Date: Mon, 31 Jul 2017 10:09:03 +0200 Subject: [PATCH 7/7] [MetaSearch] Make dialog element size dynamic --- .../MetaSearch/ui/newconnectiondialog.ui | 143 +++++++----------- 1 file changed, 54 insertions(+), 89 deletions(-) diff --git a/python/plugins/MetaSearch/ui/newconnectiondialog.ui b/python/plugins/MetaSearch/ui/newconnectiondialog.ui index 4ec6ebba1e2..adab944add4 100644 --- a/python/plugins/MetaSearch/ui/newconnectiondialog.ui +++ b/python/plugins/MetaSearch/ui/newconnectiondialog.ui @@ -6,35 +6,74 @@ 0 0 - 494 - 224 + 585 + 327 Create a new Catalog connection - - - - - - - URL - - - - + Name - + - + + + + URL + + + + + + + + + + Authentication + + + + + + If the service requires basic authentication, enter a user name and optional password + + + true + + + + + + + User name + + + + + + + + + + Password + + + + + + + + + + Qt::Horizontal @@ -44,85 +83,11 @@ - - - - 0 - - - - Authentication - - - - - 10 - 10 - 421 - 16 - - - - If the service requires basic authentication, enter a user name and optional password - - - - - - 10 - 30 - 51 - 16 - - - - User name - - - - - - 10 - 60 - 46 - 13 - - - - Password - - - - - - 80 - 30 - 341 - 20 - - - - - - - 80 - 60 - 341 - 20 - - - - - - leName leURL - leUsername - lePassword - tabNewConnectionOptions buttonBox