Skip to content

Commit 0db8a58

Browse files
authoredJul 31, 2017
Merge pull request #4944 from m-kuhn/PyOverrideCursor
Safer cursor overriding for python
2 parents cf753e9 + 1da9c60 commit 0db8a58

22 files changed

+571
-671
lines changed
 

‎python/console/console_editor.py

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
from qgis.PyQt.Qsci import QsciScintilla, QsciLexerPython, QsciAPIs, QsciStyle
2828
from qgis.core import QgsApplication, QgsSettings
2929
from qgis.gui import QgsMessageBar
30+
from qgis.utils import OverrideCursor
3031
import sys
3132
import os
3233
import subprocess
@@ -726,10 +727,9 @@ def focusInEvent(self, e):
726727
file = open(pathfile, "r")
727728
fileLines = file.readlines()
728729
file.close()
729-
QApplication.setOverrideCursor(Qt.WaitCursor)
730-
for line in reversed(fileLines):
731-
self.insert(line)
732-
QApplication.restoreOverrideCursor()
730+
with OverrideCursor(Qt.WaitCursor):
731+
for line in reversed(fileLines):
732+
self.insert(line)
733733
self.setModified(False)
734734
self.endUndoAction()
735735

@@ -785,11 +785,10 @@ def loadFile(self, filename, modified):
785785
fn = codecs.open(filename, "rb", encoding='utf-8')
786786
txt = fn.read()
787787
fn.close()
788-
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
789-
self.newEditor.setText(txt)
790-
if self.readOnly:
791-
self.newEditor.setReadOnly(self.readOnly)
792-
QApplication.restoreOverrideCursor()
788+
with OverrideCursor(Qt.WaitCursor):
789+
self.newEditor.setText(txt)
790+
if self.readOnly:
791+
self.newEditor.setReadOnly(self.readOnly)
793792
self.newEditor.setModified(modified)
794793
self.newEditor.recolor()
795794

@@ -1259,9 +1258,8 @@ def refreshSettingsEditor(self):
12591258
if objInspectorEnabled:
12601259
cW = self.currentWidget()
12611260
if cW and not self.parent.listClassMethod.isVisible():
1262-
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
1263-
self.listObject(cW)
1264-
QApplication.restoreOverrideCursor()
1261+
with OverrideCursor(Qt.WaitCursor):
1262+
self.listObject(cW)
12651263

12661264
def changeLastDirPath(self, tab):
12671265
tabWidget = self.widget(tab)

‎python/plugins/MetaSearch/dialogs/maindialog.py

Lines changed: 27 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
QgsCoordinateTransform, QgsGeometry, QgsPointXY,
4747
QgsProviderRegistry, QgsSettings)
4848
from qgis.gui import QgsRubberBand
49+
from qgis.utils import OverrideCursor
4950

5051
from owslib.csw import CatalogueServiceWeb # spellok
5152
from owslib.fes import BBox, PropertyIsLike
@@ -281,8 +282,6 @@ def connection_info(self):
281282
if not self._get_csw():
282283
return
283284

284-
QApplication.restoreOverrideCursor()
285-
286285
if self.catalog: # display service metadata
287286
self.btnCapabilities.setEnabled(True)
288287
metadata = render_template('en', self.context,
@@ -490,25 +489,22 @@ def search(self):
490489
# TODO: allow users to select resources types
491490
# to find ('service', 'dataset', etc.)
492491
try:
493-
self.catalog.getrecords2(constraints=self.constraints,
494-
maxrecords=self.maxrecords, esn='full')
492+
with OverrideCursor(Qt.WaitCursor):
493+
self.catalog.getrecords2(constraints=self.constraints,
494+
maxrecords=self.maxrecords, esn='full')
495495
except ExceptionReport as err:
496-
QApplication.restoreOverrideCursor()
497496
QMessageBox.warning(self, self.tr('Search error'),
498497
self.tr('Search error: {0}').format(err))
499498
return
500499
except Exception as err:
501-
QApplication.restoreOverrideCursor()
502500
QMessageBox.warning(self, self.tr('Connection error'),
503501
self.tr('Connection error: {0}').format(err))
504502
return
505503

506504
if self.catalog.results['matches'] == 0:
507-
QApplication.restoreOverrideCursor()
508505
self.lblResults.setText(self.tr('0 results'))
509506
return
510507

511-
QApplication.restoreOverrideCursor()
512508
self.display_results()
513509

514510
def display_results(self):
@@ -675,25 +671,20 @@ def navigate(self):
675671
else:
676672
return
677673

678-
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
679-
680674
try:
681-
self.catalog.getrecords2(constraints=self.constraints,
682-
maxrecords=self.maxrecords,
683-
startposition=self.startfrom, esn='full')
675+
with OverrideCursor(Qt.WaitCursor):
676+
self.catalog.getrecords2(constraints=self.constraints,
677+
maxrecords=self.maxrecords,
678+
startposition=self.startfrom, esn='full')
684679
except ExceptionReport as err:
685-
QApplication.restoreOverrideCursor()
686680
QMessageBox.warning(self, self.tr('Search error'),
687681
self.tr('Search error: {0}').format(err))
688682
return
689683
except Exception as err:
690-
QApplication.restoreOverrideCursor()
691684
QMessageBox.warning(self, self.tr('Connection error'),
692685
self.tr('Connection error: {0}').format(err))
693686
return
694687

695-
QApplication.restoreOverrideCursor()
696-
697688
self.display_results()
698689

699690
def add_to_ows(self):
@@ -727,8 +718,6 @@ def add_to_ows(self):
727718
stype = ['ESRI:ArcGIS:FeatureServer', 'afs', 'arcgisfeatureserver']
728719
data_url = item_data['afs'].split('FeatureServer')[0] + 'FeatureServer'
729720

730-
QApplication.restoreOverrideCursor()
731-
732721
sname = '%s from MetaSearch' % stype[1]
733722

734723
# store connection
@@ -820,26 +809,22 @@ def show_metadata(self):
820809
identifier = get_item_data(item, 'identifier')
821810

822811
try:
823-
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
824-
cat = CatalogueServiceWeb(self.catalog_url, timeout=self.timeout, # spellok
825-
username=self.catalog_username,
826-
password=self.catalog_password)
827-
cat.getrecordbyid(
828-
[self.catalog.records[identifier].identifier])
812+
with OverrideCursor(Qt.WaitCursor):
813+
cat = CatalogueServiceWeb(self.catalog_url, timeout=self.timeout, # spellok
814+
username=self.catalog_username,
815+
password=self.catalog_password)
816+
cat.getrecordbyid(
817+
[self.catalog.records[identifier].identifier])
829818
except ExceptionReport as err:
830-
QApplication.restoreOverrideCursor()
831819
QMessageBox.warning(self, self.tr('GetRecords error'),
832820
self.tr('Error getting response: {0}').format(err))
833821
return
834822
except KeyError as err:
835823
QMessageBox.warning(self,
836824
self.tr('Record parsing error'),
837825
self.tr('Unable to locate record identifier'))
838-
QApplication.restoreOverrideCursor()
839826
return
840827

841-
QApplication.restoreOverrideCursor()
842-
843828
record = cat.records[identifier]
844829
record.xml_url = cat.request
845830

@@ -902,21 +887,20 @@ def _get_csw(self):
902887
"""convenience function to init owslib.csw.CatalogueServiceWeb""" # spellok
903888

904889
# connect to the server
905-
try:
906-
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
907-
self.catalog = CatalogueServiceWeb(self.catalog_url, # spellok
908-
timeout=self.timeout,
909-
username=self.catalog_username,
910-
password=self.catalog_password)
911-
return True
912-
except ExceptionReport as err:
913-
msg = self.tr('Error connecting to service: {0}').format(err)
914-
except ValueError as err:
915-
msg = self.tr('Value Error: {0}').format(err)
916-
except Exception as err:
917-
msg = self.tr('Unknown Error: {0}').format(err)
890+
with OverrideCursor(Qt.WaitCursor):
891+
try:
892+
self.catalog = CatalogueServiceWeb(self.catalog_url, # spellok
893+
timeout=self.timeout,
894+
username=self.catalog_username,
895+
password=self.catalog_password)
896+
return True
897+
except ExceptionReport as err:
898+
msg = self.tr('Error connecting to service: {0}').format(err)
899+
except ValueError as err:
900+
msg = self.tr('Value Error: {0}').format(err)
901+
except Exception as err:
902+
msg = self.tr('Unknown Error: {0}').format(err)
918903

919-
QApplication.restoreOverrideCursor()
920904
QMessageBox.warning(self, self.tr('CSW Connection error'), msg)
921905
return False
922906

‎python/plugins/MetaSearch/ui/newconnectiondialog.ui

Lines changed: 52 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -6,35 +6,74 @@
66
<rect>
77
<x>0</x>
88
<y>0</y>
9-
<width>494</width>
10-
<height>224</height>
9+
<width>585</width>
10+
<height>327</height>
1111
</rect>
1212
</property>
1313
<property name="windowTitle">
1414
<string>Create a new Catalog connection</string>
1515
</property>
1616
<layout class="QGridLayout" name="gridLayout">
17-
<item row="2" column="2">
18-
<widget class="QLineEdit" name="leURL"/>
19-
</item>
20-
<item row="2" column="0">
21-
<widget class="QLabel" name="label_2">
17+
<item row="0" column="0">
18+
<widget class="QLabel" name="label">
2219
<property name="text">
23-
<string>URL</string>
20+
<string>Name</string>
2421
</property>
2522
</widget>
2623
</item>
24+
<item row="0" column="1">
25+
<widget class="QLineEdit" name="leName"/>
26+
</item>
2727
<item row="1" column="0">
28-
<widget class="QLabel" name="label">
28+
<widget class="QLabel" name="label_2">
2929
<property name="text">
30-
<string>Name</string>
30+
<string>URL</string>
3131
</property>
3232
</widget>
3333
</item>
34-
<item row="1" column="2">
35-
<widget class="QLineEdit" name="leName"/>
34+
<item row="1" column="1">
35+
<widget class="QLineEdit" name="leURL"/>
36+
</item>
37+
<item row="2" column="0" colspan="2">
38+
<widget class="QGroupBox" name="authenticationGroupBox">
39+
<property name="title">
40+
<string>Authentication</string>
41+
</property>
42+
<layout class="QFormLayout" name="formLayout_2">
43+
<item row="0" column="0" colspan="2">
44+
<widget class="QLabel" name="label_3">
45+
<property name="text">
46+
<string>If the service requires basic authentication, enter a user name and optional password</string>
47+
</property>
48+
<property name="wordWrap">
49+
<bool>true</bool>
50+
</property>
51+
</widget>
52+
</item>
53+
<item row="1" column="0">
54+
<widget class="QLabel" name="label_4">
55+
<property name="text">
56+
<string>User name</string>
57+
</property>
58+
</widget>
59+
</item>
60+
<item row="1" column="1">
61+
<widget class="QLineEdit" name="leUsername"/>
62+
</item>
63+
<item row="2" column="0">
64+
<widget class="QLabel" name="label_5">
65+
<property name="text">
66+
<string>Password</string>
67+
</property>
68+
</widget>
69+
</item>
70+
<item row="2" column="1">
71+
<widget class="QLineEdit" name="lePassword"/>
72+
</item>
73+
</layout>
74+
</widget>
3675
</item>
37-
<item row="5" column="2">
76+
<item row="3" column="1">
3877
<widget class="QDialogButtonBox" name="buttonBox">
3978
<property name="orientation">
4079
<enum>Qt::Horizontal</enum>
@@ -44,85 +83,11 @@
4483
</property>
4584
</widget>
4685
</item>
47-
<item row="3" column="2">
48-
<widget class="QTabWidget" name="tabNewConnectionOptions">
49-
<property name="currentIndex">
50-
<number>0</number>
51-
</property>
52-
<widget class="QWidget" name="tab">
53-
<attribute name="title">
54-
<string>Authentication</string>
55-
</attribute>
56-
<widget class="QLabel" name="label_3">
57-
<property name="geometry">
58-
<rect>
59-
<x>10</x>
60-
<y>10</y>
61-
<width>421</width>
62-
<height>16</height>
63-
</rect>
64-
</property>
65-
<property name="text">
66-
<string>If the service requires basic authentication, enter a user name and optional password</string>
67-
</property>
68-
</widget>
69-
<widget class="QLabel" name="label_4">
70-
<property name="geometry">
71-
<rect>
72-
<x>10</x>
73-
<y>30</y>
74-
<width>51</width>
75-
<height>16</height>
76-
</rect>
77-
</property>
78-
<property name="text">
79-
<string>User name</string>
80-
</property>
81-
</widget>
82-
<widget class="QLabel" name="label_5">
83-
<property name="geometry">
84-
<rect>
85-
<x>10</x>
86-
<y>60</y>
87-
<width>46</width>
88-
<height>13</height>
89-
</rect>
90-
</property>
91-
<property name="text">
92-
<string>Password</string>
93-
</property>
94-
</widget>
95-
<widget class="QLineEdit" name="leUsername">
96-
<property name="geometry">
97-
<rect>
98-
<x>80</x>
99-
<y>30</y>
100-
<width>341</width>
101-
<height>20</height>
102-
</rect>
103-
</property>
104-
</widget>
105-
<widget class="QLineEdit" name="lePassword">
106-
<property name="geometry">
107-
<rect>
108-
<x>80</x>
109-
<y>60</y>
110-
<width>341</width>
111-
<height>20</height>
112-
</rect>
113-
</property>
114-
</widget>
115-
</widget>
116-
</widget>
117-
</item>
11886
</layout>
11987
</widget>
12088
<tabstops>
12189
<tabstop>leName</tabstop>
12290
<tabstop>leURL</tabstop>
123-
<tabstop>leUsername</tabstop>
124-
<tabstop>lePassword</tabstop>
125-
<tabstop>tabNewConnectionOptions</tabstop>
12691
<tabstop>buttonBox</tabstop>
12792
</tabstops>
12893
<resources/>

‎python/plugins/db_manager/db_manager.py

Lines changed: 28 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232

3333
from qgis.gui import QgsMessageBar
3434
from qgis.core import QgsSettings, QgsMapLayer
35+
from qgis.utils import OverrideCursor
36+
3537
from .info_viewer import InfoViewer
3638
from .table_viewer import TableViewer
3739
from .layer_preview import LayerPreview
@@ -72,29 +74,23 @@ def closeEvent(self, e):
7274
QMainWindow.closeEvent(self, e)
7375

7476
def refreshItem(self, item=None):
75-
QApplication.setOverrideCursor(Qt.WaitCursor)
76-
try:
77-
if item is None:
78-
item = self.tree.currentItem()
79-
self.tree.refreshItem(item) # refresh item children in the db tree
80-
except BaseError as e:
81-
DlgDbError.showError(e, self)
82-
return
83-
finally:
84-
QApplication.restoreOverrideCursor()
77+
with OverrideCursor(Qt.WaitCursor):
78+
try:
79+
if item is None:
80+
item = self.tree.currentItem()
81+
self.tree.refreshItem(item) # refresh item children in the db tree
82+
except BaseError as e:
83+
DlgDbError.showError(e, self)
8584

8685
def itemChanged(self, item):
87-
QApplication.setOverrideCursor(Qt.WaitCursor)
88-
try:
89-
self.reloadButtons()
90-
# clear preview, this will delete the layer in preview tab
91-
self.preview.loadPreview(None)
92-
self.refreshTabs()
93-
except BaseError as e:
94-
DlgDbError.showError(e, self)
95-
return
96-
finally:
97-
QApplication.restoreOverrideCursor()
86+
with OverrideCursor(Qt.WaitCursor):
87+
try:
88+
self.reloadButtons()
89+
# clear preview, this will delete the layer in preview tab
90+
self.preview.loadPreview(None)
91+
self.refreshTabs()
92+
except BaseError as e:
93+
DlgDbError.showError(e, self)
9894

9995
def reloadButtons(self):
10096
db = self.tree.currentDatabase()
@@ -114,14 +110,11 @@ def reloadButtons(self):
114110
self._lastDb.registerAllActions(self)
115111

116112
def tabChanged(self, index):
117-
QApplication.setOverrideCursor(Qt.WaitCursor)
118-
try:
119-
self.refreshTabs()
120-
except BaseError as e:
121-
DlgDbError.showError(e, self)
122-
return
123-
finally:
124-
QApplication.restoreOverrideCursor()
113+
with OverrideCursor(Qt.WaitCursor):
114+
try:
115+
self.refreshTabs()
116+
except BaseError as e:
117+
DlgDbError.showError(e, self)
125118

126119
def refreshTabs(self):
127120
index = self.tabs.currentIndex()
@@ -300,17 +293,12 @@ def invokeCallback(self, callback, *params):
300293
This method takes care to override and restore the cursor,
301294
but also catches exceptions and displays the error dialog.
302295
"""
303-
QApplication.setOverrideCursor(Qt.WaitCursor)
304-
try:
305-
callback(self.tree.currentItem(), self.sender(), self, *params)
306-
307-
except BaseError as e:
308-
# catch database errors and display the error dialog
309-
DlgDbError.showError(e, self)
310-
return
311-
312-
finally:
313-
QApplication.restoreOverrideCursor()
296+
with OverrideCursor(Qt.WaitCursor):
297+
try:
298+
callback(self.tree.currentItem(), self.sender(), self, *params)
299+
except BaseError as e:
300+
# catch database errors and display the error dialog
301+
DlgDbError.showError(e, self)
314302

315303
def unregisterAction(self, action, menuName):
316304
if not hasattr(self, '_registeredDbActions'):

‎python/plugins/db_manager/db_model.py

Lines changed: 26 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
from .dlg_db_error import DlgDbError
3333

3434
from qgis.core import QgsDataSourceUri, QgsVectorLayer, QgsRasterLayer, QgsMimeDataUtils
35+
from qgis.utils import OverrideCursor
3536

3637
from . import resources_rc # NOQA
3738

@@ -458,17 +459,15 @@ def setData(self, index, value, role):
458459
if new_value == obj.name:
459460
return False
460461

461-
QApplication.setOverrideCursor(Qt.WaitCursor)
462-
try:
463-
obj.rename(new_value)
464-
self._onDataChanged(index)
465-
except BaseError as e:
466-
DlgDbError.showError(e, self.treeView)
467-
return False
468-
finally:
469-
QApplication.restoreOverrideCursor()
470-
471-
return True
462+
with OverrideCursor(Qt.WaitCursor):
463+
try:
464+
obj.rename(new_value)
465+
self._onDataChanged(index)
466+
except BaseError as e:
467+
DlgDbError.showError(e, self.treeView)
468+
return False
469+
else:
470+
return True
472471

473472
return False
474473

@@ -480,27 +479,23 @@ def removeRows(self, row, count, parent):
480479
self.endRemoveRows()
481480

482481
def _refreshIndex(self, index, force=False):
483-
QApplication.setOverrideCursor(Qt.WaitCursor)
484-
try:
485-
item = index.internalPointer() if index.isValid() else self.rootItem
486-
prevPopulated = item.populated
487-
if prevPopulated:
488-
self.removeRows(0, self.rowCount(index), index)
489-
item.populated = False
490-
if prevPopulated or force:
491-
if item.populate():
492-
for child in item.childItems:
493-
child.changed.connect(partial(self.refreshItem, child))
494-
self._onDataChanged(index)
495-
else:
496-
self.notPopulated.emit(index)
497-
498-
except BaseError:
499-
item.populated = False
500-
return
482+
with OverrideCursor(Qt.WaitCursor):
483+
try:
484+
item = index.internalPointer() if index.isValid() else self.rootItem
485+
prevPopulated = item.populated
486+
if prevPopulated:
487+
self.removeRows(0, self.rowCount(index), index)
488+
item.populated = False
489+
if prevPopulated or force:
490+
if item.populate():
491+
for child in item.childItems:
492+
child.changed.connect(partial(self.refreshItem, child))
493+
self._onDataChanged(index)
494+
else:
495+
self.notPopulated.emit(index)
501496

502-
finally:
503-
QApplication.restoreOverrideCursor()
497+
except BaseError:
498+
item.populated = False
504499

505500
def _onDataChanged(self, indexFrom, indexTo=None):
506501
if indexTo is None:

‎python/plugins/db_manager/dlg_add_geometry_column.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
from qgis.PyQt.QtCore import Qt
2626
from qgis.PyQt.QtWidgets import QDialog, QMessageBox, QApplication
27+
from qgis.utils import OverrideCursor
2728

2829
from .db_plugins.plugin import DbError
2930
from .dlg_db_error import DlgDbError
@@ -59,13 +60,11 @@ def createGeomColumn(self):
5960
createSpatialIndex = False
6061

6162
# now create the geometry column
62-
QApplication.setOverrideCursor(Qt.WaitCursor)
63-
try:
64-
self.table.addGeometryColumn(name, geom_type, srid, dim, createSpatialIndex)
65-
except DbError as e:
66-
DlgDbError.showError(e, self)
67-
return
68-
finally:
69-
QApplication.restoreOverrideCursor()
63+
with OverrideCursor(Qt.WaitCursor):
64+
try:
65+
self.table.addGeometryColumn(name, geom_type, srid, dim, createSpatialIndex)
66+
except DbError as e:
67+
DlgDbError.showError(e, self)
68+
return
7069

7170
self.accept()

‎python/plugins/db_manager/dlg_create_constraint.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
from qgis.PyQt.QtCore import Qt
2626
from qgis.PyQt.QtWidgets import QDialog, QApplication
27+
from qgis.utils import OverrideCursor
2728

2829
from .db_plugins.plugin import DbError
2930
from .dlg_db_error import DlgDbError
@@ -52,14 +53,12 @@ def createConstraint(self):
5253
constr = self.getConstraint()
5354

5455
# now create the constraint
55-
QApplication.setOverrideCursor(Qt.WaitCursor)
56-
try:
57-
self.table.addConstraint(constr)
58-
except DbError as e:
59-
DlgDbError.showError(e, self)
60-
return
61-
finally:
62-
QApplication.restoreOverrideCursor()
56+
with OverrideCursor(Qt.WaitCursor):
57+
try:
58+
self.table.addConstraint(constr)
59+
except DbError as e:
60+
DlgDbError.showError(e, self)
61+
return
6362

6463
self.accept()
6564

‎python/plugins/db_manager/dlg_create_index.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
from qgis.PyQt.QtCore import Qt
2626
from qgis.PyQt.QtWidgets import QDialog, QMessageBox, QApplication
27+
from qgis.utils import OverrideCursor
2728

2829
from .db_plugins.plugin import DbError
2930
from .dlg_db_error import DlgDbError
@@ -60,14 +61,12 @@ def createIndex(self):
6061
return
6162

6263
# now create the index
63-
QApplication.setOverrideCursor(Qt.WaitCursor)
64-
try:
65-
self.table.addIndex(idx)
66-
except DbError as e:
67-
DlgDbError.showError(e, self)
68-
return
69-
finally:
70-
QApplication.restoreOverrideCursor()
64+
with OverrideCursor(Qt.WaitCursor):
65+
try:
66+
self.table.addIndex(idx)
67+
except DbError as e:
68+
DlgDbError.showError(e, self)
69+
return
7170

7271
self.accept()
7372

‎python/plugins/db_manager/dlg_create_table.py

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
from qgis.PyQt.QtWidgets import QItemDelegate, QComboBox, QDialog, QPushButton, QDialogButtonBox, QMessageBox, QApplication
2929
from qgis.PyQt.QtCore import QItemSelectionModel, pyqtSignal
3030

31+
from qgis.utils import OverrideCursor
32+
3133
from .db_plugins.data_model import TableFieldsModel
3234
from .db_plugins.plugin import DbError, ConnectionError
3335
from .dlg_db_error import DlgDbError
@@ -297,19 +299,16 @@ def createTable(self):
297299
flds[pk_index].primaryKey = True
298300

299301
# commit to DB
300-
QApplication.setOverrideCursor(Qt.WaitCursor)
301-
try:
302-
if not useGeomColumn:
303-
self.db.createTable(table, flds, schema)
304-
else:
305-
geom = geomColumn, geomType, geomSrid, geomDim, useSpatialIndex
306-
self.db.createVectorTable(table, flds, geom, schema)
307-
308-
except (ConnectionError, DbError) as e:
309-
DlgDbError.showError(e, self)
302+
with OverrideCursor(Qt.WaitCursor):
303+
try:
304+
if not useGeomColumn:
305+
self.db.createTable(table, flds, schema)
306+
else:
307+
geom = geomColumn, geomType, geomSrid, geomDim, useSpatialIndex
308+
self.db.createVectorTable(table, flds, geom, schema)
309+
310+
except (ConnectionError, DbError) as e:
311+
DlgDbError.showError(e, self)
310312
return
311313

312-
finally:
313-
QApplication.restoreOverrideCursor()
314-
315314
QMessageBox.information(self, self.tr("Good"), self.tr("everything went fine"))

‎python/plugins/db_manager/dlg_export_vector.py

Lines changed: 43 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
QgsCoordinateReferenceSystem,
3333
QgsVectorLayerExporter,
3434
QgsSettings)
35+
from qgis.utils import OverrideCursor
3536

3637
from .ui.ui_DlgExportVector import Ui_DbManagerDlgExportVector as Ui_Dialog
3738

@@ -145,51 +146,48 @@ def accept(self):
145146
self.tr("Invalid target srid: must be an integer"))
146147
return
147148

148-
# override cursor
149-
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
150-
# store current input layer crs, so I can restore it later
151-
prevInCrs = self.inLayer.crs()
152-
try:
153-
uri = self.editOutputFile.text()
154-
providerName = "ogr"
155-
156-
options = {}
157-
158-
# set the OGR driver will be used
159-
driverName = self.cboFileFormat.currentData()
160-
options['driverName'] = driverName
161-
162-
# set the output file encoding
163-
if self.chkEncoding.isEnabled() and self.chkEncoding.isChecked():
164-
enc = self.cboEncoding.currentText()
165-
options['fileEncoding'] = enc
166-
167-
if self.chkDropTable.isChecked():
168-
options['overwrite'] = True
169-
170-
outCrs = QgsCoordinateReferenceSystem()
171-
if self.chkTargetSrid.isEnabled() and self.chkTargetSrid.isChecked():
172-
targetSrid = int(self.editTargetSrid.text())
173-
outCrs = QgsCoordinateReferenceSystem(targetSrid)
174-
175-
# update input layer crs
176-
if self.chkSourceSrid.isEnabled() and self.chkSourceSrid.isChecked():
177-
sourceSrid = int(self.editSourceSrid.text())
178-
inCrs = QgsCoordinateReferenceSystem(sourceSrid)
179-
self.inLayer.setCrs(inCrs)
180-
181-
# do the export!
182-
ret, errMsg = QgsVectorLayerExporter.exportLayer(self.inLayer, uri, providerName, outCrs,
183-
False, options)
184-
except Exception as e:
185-
ret = -1
186-
errMsg = str(e)
187-
188-
finally:
189-
# restore input layer crs and encoding
190-
self.inLayer.setCrs(prevInCrs)
191-
# restore cursor
192-
QApplication.restoreOverrideCursor()
149+
with OverrideCursor(Qt.WaitCursor):
150+
# store current input layer crs, so I can restore it later
151+
prevInCrs = self.inLayer.crs()
152+
try:
153+
uri = self.editOutputFile.text()
154+
providerName = "ogr"
155+
156+
options = {}
157+
158+
# set the OGR driver will be used
159+
driverName = self.cboFileFormat.currentData()
160+
options['driverName'] = driverName
161+
162+
# set the output file encoding
163+
if self.chkEncoding.isEnabled() and self.chkEncoding.isChecked():
164+
enc = self.cboEncoding.currentText()
165+
options['fileEncoding'] = enc
166+
167+
if self.chkDropTable.isChecked():
168+
options['overwrite'] = True
169+
170+
outCrs = QgsCoordinateReferenceSystem()
171+
if self.chkTargetSrid.isEnabled() and self.chkTargetSrid.isChecked():
172+
targetSrid = int(self.editTargetSrid.text())
173+
outCrs = QgsCoordinateReferenceSystem(targetSrid)
174+
175+
# update input layer crs
176+
if self.chkSourceSrid.isEnabled() and self.chkSourceSrid.isChecked():
177+
sourceSrid = int(self.editSourceSrid.text())
178+
inCrs = QgsCoordinateReferenceSystem(sourceSrid)
179+
self.inLayer.setCrs(inCrs)
180+
181+
# do the export!
182+
ret, errMsg = QgsVectorLayerExporter.exportLayer(self.inLayer, uri, providerName, outCrs,
183+
False, options)
184+
except Exception as e:
185+
ret = -1
186+
errMsg = str(e)
187+
188+
finally:
189+
# restore input layer crs and encoding
190+
self.inLayer.setCrs(prevInCrs)
193191

194192
if ret != 0:
195193
QMessageBox.warning(self, self.tr("Export to file"), self.tr("Error {0}\n{1}").format(ret, errMsg))

‎python/plugins/db_manager/dlg_import_vector.py

Lines changed: 77 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
QgsProject,
3838
QgsSettings)
3939
from qgis.gui import QgsMessageViewer
40+
from qgis.utils import OverrideCursor
4041

4142
from .ui.ui_DlgImportVector import Ui_DbManagerDlgImportVector as Ui_Dialog
4243

@@ -292,85 +293,82 @@ def accept(self):
292293
self.tr("Invalid target srid: must be an integer"))
293294
return
294295

295-
# override cursor
296-
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
297-
# store current input layer crs and encoding, so I can restore it
298-
prevInCrs = self.inLayer.crs()
299-
prevInEncoding = self.inLayer.dataProvider().encoding()
300-
301-
try:
302-
schema = self.outUri.schema() if not self.cboSchema.isEnabled() else self.cboSchema.currentText()
303-
table = self.cboTable.currentText()
304-
305-
# get pk and geom field names from the source layer or use the
306-
# ones defined by the user
307-
srcUri = QgsDataSourceUri(self.inLayer.source())
308-
309-
pk = srcUri.keyColumn() if not self.chkPrimaryKey.isChecked() else self.editPrimaryKey.text()
310-
if not pk:
311-
pk = self.default_pk
312-
313-
if self.inLayer.isSpatial() and self.chkGeomColumn.isEnabled():
314-
geom = srcUri.geometryColumn() if not self.chkGeomColumn.isChecked() else self.editGeomColumn.text()
315-
if not geom:
316-
geom = self.default_geom
317-
else:
318-
geom = None
319-
320-
options = {}
321-
if self.chkLowercaseFieldNames.isEnabled() and self.chkLowercaseFieldNames.isChecked():
322-
pk = pk.lower()
323-
if geom:
324-
geom = geom.lower()
325-
options['lowercaseFieldNames'] = True
326-
327-
# get output params, update output URI
328-
self.outUri.setDataSource(schema, table, geom, "", pk)
329-
typeName = self.db.dbplugin().typeName()
330-
providerName = self.db.dbplugin().providerName()
331-
if typeName == 'gpkg':
332-
uri = self.outUri.database()
333-
options['update'] = True
334-
options['driverName'] = 'GPKG'
335-
options['layerName'] = table
336-
else:
337-
uri = self.outUri.uri(False)
338-
339-
if self.chkDropTable.isChecked():
340-
options['overwrite'] = True
341-
342-
if self.chkSinglePart.isEnabled() and self.chkSinglePart.isChecked():
343-
options['forceSinglePartGeometryType'] = True
344-
345-
outCrs = QgsCoordinateReferenceSystem()
346-
if self.chkTargetSrid.isEnabled() and self.chkTargetSrid.isChecked():
347-
targetSrid = int(self.editTargetSrid.text())
348-
outCrs = QgsCoordinateReferenceSystem(targetSrid)
349-
350-
# update input layer crs and encoding
351-
if self.chkSourceSrid.isEnabled() and self.chkSourceSrid.isChecked():
352-
sourceSrid = int(self.editSourceSrid.text())
353-
inCrs = QgsCoordinateReferenceSystem(sourceSrid)
354-
self.inLayer.setCrs(inCrs)
355-
356-
if self.chkEncoding.isEnabled() and self.chkEncoding.isChecked():
357-
enc = self.cboEncoding.currentText()
358-
self.inLayer.setProviderEncoding(enc)
359-
360-
onlySelected = self.chkSelectedFeatures.isChecked()
361-
362-
# do the import!
363-
ret, errMsg = QgsVectorLayerExporter.exportLayer(self.inLayer, uri, providerName, outCrs, onlySelected, options)
364-
except Exception as e:
365-
ret = -1
366-
errMsg = str(e)
367-
368-
finally:
369-
# restore input layer crs and encoding
370-
self.inLayer.setCrs(prevInCrs)
371-
self.inLayer.setProviderEncoding(prevInEncoding)
372-
# restore cursor
373-
QApplication.restoreOverrideCursor()
296+
with OverrideCursor(Qt.WaitCursor):
297+
# store current input layer crs and encoding, so I can restore it
298+
prevInCrs = self.inLayer.crs()
299+
prevInEncoding = self.inLayer.dataProvider().encoding()
300+
301+
try:
302+
schema = self.outUri.schema() if not self.cboSchema.isEnabled() else self.cboSchema.currentText()
303+
table = self.cboTable.currentText()
304+
305+
# get pk and geom field names from the source layer or use the
306+
# ones defined by the user
307+
srcUri = QgsDataSourceUri(self.inLayer.source())
308+
309+
pk = srcUri.keyColumn() if not self.chkPrimaryKey.isChecked() else self.editPrimaryKey.text()
310+
if not pk:
311+
pk = self.default_pk
312+
313+
if self.inLayer.isSpatial() and self.chkGeomColumn.isEnabled():
314+
geom = srcUri.geometryColumn() if not self.chkGeomColumn.isChecked() else self.editGeomColumn.text()
315+
if not geom:
316+
geom = self.default_geom
317+
else:
318+
geom = None
319+
320+
options = {}
321+
if self.chkLowercaseFieldNames.isEnabled() and self.chkLowercaseFieldNames.isChecked():
322+
pk = pk.lower()
323+
if geom:
324+
geom = geom.lower()
325+
options['lowercaseFieldNames'] = True
326+
327+
# get output params, update output URI
328+
self.outUri.setDataSource(schema, table, geom, "", pk)
329+
typeName = self.db.dbplugin().typeName()
330+
providerName = self.db.dbplugin().providerName()
331+
if typeName == 'gpkg':
332+
uri = self.outUri.database()
333+
options['update'] = True
334+
options['driverName'] = 'GPKG'
335+
options['layerName'] = table
336+
else:
337+
uri = self.outUri.uri(False)
338+
339+
if self.chkDropTable.isChecked():
340+
options['overwrite'] = True
341+
342+
if self.chkSinglePart.isEnabled() and self.chkSinglePart.isChecked():
343+
options['forceSinglePartGeometryType'] = True
344+
345+
outCrs = QgsCoordinateReferenceSystem()
346+
if self.chkTargetSrid.isEnabled() and self.chkTargetSrid.isChecked():
347+
targetSrid = int(self.editTargetSrid.text())
348+
outCrs = QgsCoordinateReferenceSystem(targetSrid)
349+
350+
# update input layer crs and encoding
351+
if self.chkSourceSrid.isEnabled() and self.chkSourceSrid.isChecked():
352+
sourceSrid = int(self.editSourceSrid.text())
353+
inCrs = QgsCoordinateReferenceSystem(sourceSrid)
354+
self.inLayer.setCrs(inCrs)
355+
356+
if self.chkEncoding.isEnabled() and self.chkEncoding.isChecked():
357+
enc = self.cboEncoding.currentText()
358+
self.inLayer.setProviderEncoding(enc)
359+
360+
onlySelected = self.chkSelectedFeatures.isChecked()
361+
362+
# do the import!
363+
ret, errMsg = QgsVectorLayerExporter.exportLayer(self.inLayer, uri, providerName, outCrs, onlySelected, options)
364+
except Exception as e:
365+
ret = -1
366+
errMsg = str(e)
367+
368+
finally:
369+
# restore input layer crs and encoding
370+
self.inLayer.setCrs(prevInCrs)
371+
self.inLayer.setProviderEncoding(prevInEncoding)
374372

375373
if ret != 0:
376374
output = QgsMessageViewer()

‎python/plugins/db_manager/dlg_sql_layer_window.py

Lines changed: 70 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
from qgis.PyQt.QtXml import QDomDocument
3333

3434
from qgis.core import QgsProject, QgsDataSourceUri
35+
from qgis.utils import OverrideCursor
3536

3637
from .db_plugins import createDbPlugin
3738
from .db_plugins.plugin import BaseError
@@ -223,37 +224,35 @@ def executeSql(self):
223224
if sql == "":
224225
return
225226

226-
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
227-
228-
# delete the old model
229-
old_model = self.viewResult.model()
230-
self.viewResult.setModel(None)
231-
if old_model:
232-
old_model.deleteLater()
233-
234-
cols = []
235-
quotedCols = []
236-
237-
try:
238-
# set the new model
239-
model = self.db.sqlResultModel(sql, self)
240-
self.viewResult.setModel(model)
241-
self.lblResult.setText(self.tr("{0} rows, {1:.1f} seconds").format(model.affectedRows(), model.secs()))
242-
cols = self.viewResult.model().columnNames()
243-
for col in cols:
244-
quotedCols.append(self.db.connector.quoteId(col))
245-
246-
except BaseError as e:
247-
QApplication.restoreOverrideCursor()
248-
DlgDbError.showError(e, self)
249-
self.uniqueModel.clear()
250-
self.geomCombo.clear()
251-
return
227+
with OverrideCursor(Qt.WaitCursor):
228+
229+
# delete the old model
230+
old_model = self.viewResult.model()
231+
self.viewResult.setModel(None)
232+
if old_model:
233+
old_model.deleteLater()
234+
235+
cols = []
236+
quotedCols = []
237+
238+
try:
239+
# set the new model
240+
model = self.db.sqlResultModel(sql, self)
241+
self.viewResult.setModel(model)
242+
self.lblResult.setText(self.tr("{0} rows, {1:.1f} seconds").format(model.affectedRows(), model.secs()))
243+
cols = self.viewResult.model().columnNames()
244+
for col in cols:
245+
quotedCols.append(self.db.connector.quoteId(col))
246+
247+
except BaseError as e:
248+
DlgDbError.showError(e, self)
249+
self.uniqueModel.clear()
250+
self.geomCombo.clear()
251+
return
252252

253-
self.setColumnCombos(cols, quotedCols)
253+
self.setColumnCombos(cols, quotedCols)
254254

255-
self.update()
256-
QApplication.restoreOverrideCursor()
255+
self.update()
257256

258257
def _getSqlLayer(self, _filter):
259258
hasUniqueField = self.uniqueColumnCheck.checkState() == Qt.Checked
@@ -311,19 +310,15 @@ def _getSqlLayer(self, _filter):
311310
return None
312311

313312
def loadSqlLayer(self):
314-
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
315-
try:
313+
with OverrideCursor(Qt.WaitCursor):
316314
layer = self._getSqlLayer(self.filter)
317315
if layer is None:
318316
return
319317

320318
QgsProject.instance().addMapLayers([layer], True)
321-
finally:
322-
QApplication.restoreOverrideCursor()
323319

324320
def updateSqlLayer(self):
325-
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
326-
try:
321+
with OverrideCursor(Qt.WaitCursor):
327322
layer = self._getSqlLayer(self.filter)
328323
if layer is None:
329324
return
@@ -341,60 +336,54 @@ def updateSqlLayer(self):
341336
self.layer.reload()
342337
self.iface.actionDraw().trigger()
343338
self.iface.mapCanvas().refresh()
344-
finally:
345-
QApplication.restoreOverrideCursor()
346339

347340
def fillColumnCombos(self):
348341
query = self._getSqlQuery()
349342
if query == "":
350343
return
351344

352-
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
353-
354-
# remove a trailing ';' from query if present
355-
if query.strip().endswith(';'):
356-
query = query.strip()[:-1]
357-
358-
# get all the columns
359-
cols = []
360-
quotedCols = []
361-
connector = self.db.connector
362-
if self.aliasSubQuery:
363-
# get a new alias
364-
aliasIndex = 0
365-
while True:
366-
alias = "_subQuery__%d" % aliasIndex
367-
escaped = re.compile('\\b("?)' + re.escape(alias) + '\\1\\b')
368-
if not escaped.search(query):
369-
break
370-
aliasIndex += 1
371-
372-
sql = u"SELECT * FROM (%s\n) AS %s LIMIT 0" % (str(query), connector.quoteId(alias))
373-
else:
374-
sql = u"SELECT * FROM (%s\n) WHERE 1=0" % str(query)
375-
376-
c = None
377-
try:
378-
c = connector._execute(None, sql)
379-
cols = connector._get_cursor_columns(c)
380-
for col in cols:
381-
quotedCols.append(connector.quoteId(col))
382-
383-
except BaseError as e:
384-
QApplication.restoreOverrideCursor()
385-
DlgDbError.showError(e, self)
386-
self.uniqueModel.clear()
387-
self.geomCombo.clear()
388-
return
389-
390-
finally:
391-
if c:
392-
c.close()
393-
del c
345+
with OverrideCursor(Qt.WaitCursor):
346+
# remove a trailing ';' from query if present
347+
if query.strip().endswith(';'):
348+
query = query.strip()[:-1]
349+
350+
# get all the columns
351+
cols = []
352+
quotedCols = []
353+
connector = self.db.connector
354+
if self.aliasSubQuery:
355+
# get a new alias
356+
aliasIndex = 0
357+
while True:
358+
alias = "_subQuery__%d" % aliasIndex
359+
escaped = re.compile('\\b("?)' + re.escape(alias) + '\\1\\b')
360+
if not escaped.search(query):
361+
break
362+
aliasIndex += 1
363+
364+
sql = u"SELECT * FROM (%s\n) AS %s LIMIT 0" % (str(query), connector.quoteId(alias))
365+
else:
366+
sql = u"SELECT * FROM (%s\n) WHERE 1=0" % str(query)
367+
368+
c = None
369+
try:
370+
c = connector._execute(None, sql)
371+
cols = connector._get_cursor_columns(c)
372+
for col in cols:
373+
quotedCols.append(connector.quoteId(col))
374+
375+
except BaseError as e:
376+
DlgDbError.showError(e, self)
377+
self.uniqueModel.clear()
378+
self.geomCombo.clear()
379+
return
394380

395-
self.setColumnCombos(cols, quotedCols)
381+
finally:
382+
if c:
383+
c.close()
384+
del c
396385

397-
QApplication.restoreOverrideCursor()
386+
self.setColumnCombos(cols, quotedCols)
398387

399388
def setColumnCombos(self, cols, quotedCols):
400389
# 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)

‎python/plugins/db_manager/dlg_sql_window.py

Lines changed: 63 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
from qgis.PyQt.Qsci import QsciAPIs
3232

3333
from qgis.core import QgsProject
34+
from qgis.utils import OverrideCursor
3435

3536
from .db_plugins.plugin import BaseError
3637
from .db_plugins.postgis.plugin import PGDatabase
@@ -182,37 +183,34 @@ def executeSql(self):
182183
if sql == "":
183184
return
184185

185-
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
186+
with OverrideCursor(Qt.WaitCursor):
187+
# delete the old model
188+
old_model = self.viewResult.model()
189+
self.viewResult.setModel(None)
190+
if old_model:
191+
old_model.deleteLater()
186192

187-
# delete the old model
188-
old_model = self.viewResult.model()
189-
self.viewResult.setModel(None)
190-
if old_model:
191-
old_model.deleteLater()
193+
cols = []
194+
quotedCols = []
192195

193-
cols = []
194-
quotedCols = []
196+
try:
197+
# set the new model
198+
model = self.db.sqlResultModel(sql, self)
199+
self.viewResult.setModel(model)
200+
self.lblResult.setText(self.tr("{0} rows, {1:.1f} seconds").format(model.affectedRows(), model.secs()))
201+
cols = self.viewResult.model().columnNames()
202+
for col in cols:
203+
quotedCols.append(self.db.connector.quoteId(col))
195204

196-
try:
197-
# set the new model
198-
model = self.db.sqlResultModel(sql, self)
199-
self.viewResult.setModel(model)
200-
self.lblResult.setText(self.tr("{0} rows, {1:.1f} seconds").format(model.affectedRows(), model.secs()))
201-
cols = self.viewResult.model().columnNames()
202-
for col in cols:
203-
quotedCols.append(self.db.connector.quoteId(col))
204-
205-
except BaseError as e:
206-
QApplication.restoreOverrideCursor()
207-
DlgDbError.showError(e, self)
208-
self.uniqueModel.clear()
209-
self.geomCombo.clear()
210-
return
205+
except BaseError as e:
206+
DlgDbError.showError(e, self)
207+
self.uniqueModel.clear()
208+
self.geomCombo.clear()
209+
return
211210

212-
self.setColumnCombos(cols, quotedCols)
211+
self.setColumnCombos(cols, quotedCols)
213212

214-
self.update()
215-
QApplication.restoreOverrideCursor()
213+
self.update()
216214

217215
def _getSqlLayer(self, _filter):
218216
hasUniqueField = self.uniqueColumnCheck.checkState() == Qt.Checked
@@ -270,67 +268,60 @@ def _getSqlLayer(self, _filter):
270268
return None
271269

272270
def loadSqlLayer(self):
273-
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
274-
try:
271+
with OverrideCursor(Qt.WaitCursor):
275272
layer = self._getSqlLayer(self.filter)
276273
if layer is None:
277274
return
278275

279276
QgsProject.instance().addMapLayers([layer], True)
280-
finally:
281-
QApplication.restoreOverrideCursor()
282277

283278
def fillColumnCombos(self):
284279
query = self._getSqlQuery()
285280
if query == "":
286281
return
287282

288-
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
289-
290-
# remove a trailing ';' from query if present
291-
if query.strip().endswith(';'):
292-
query = query.strip()[:-1]
293-
294-
# get all the columns
295-
cols = []
296-
quotedCols = []
297-
connector = self.db.connector
298-
if self.aliasSubQuery:
299-
# get a new alias
300-
aliasIndex = 0
301-
while True:
302-
alias = "_subQuery__%d" % aliasIndex
303-
escaped = re.compile('\\b("?)' + re.escape(alias) + '\\1\\b')
304-
if not escaped.search(query):
305-
break
306-
aliasIndex += 1
307-
308-
sql = u"SELECT * FROM (%s\n) AS %s LIMIT 0" % (str(query), connector.quoteId(alias))
309-
else:
310-
sql = u"SELECT * FROM (%s\n) WHERE 1=0" % str(query)
283+
with OverrideCursor(Qt.WaitCursor):
284+
# remove a trailing ';' from query if present
285+
if query.strip().endswith(';'):
286+
query = query.strip()[:-1]
287+
288+
# get all the columns
289+
cols = []
290+
quotedCols = []
291+
connector = self.db.connector
292+
if self.aliasSubQuery:
293+
# get a new alias
294+
aliasIndex = 0
295+
while True:
296+
alias = "_subQuery__%d" % aliasIndex
297+
escaped = re.compile('\\b("?)' + re.escape(alias) + '\\1\\b')
298+
if not escaped.search(query):
299+
break
300+
aliasIndex += 1
301+
302+
sql = u"SELECT * FROM (%s\n) AS %s LIMIT 0" % (str(query), connector.quoteId(alias))
303+
else:
304+
sql = u"SELECT * FROM (%s\n) WHERE 1=0" % str(query)
311305

312-
c = None
313-
try:
314-
c = connector._execute(None, sql)
315-
cols = connector._get_cursor_columns(c)
316-
for col in cols:
317-
quotedCols.append(connector.quoteId(col))
318-
319-
except BaseError as e:
320-
QApplication.restoreOverrideCursor()
321-
DlgDbError.showError(e, self)
322-
self.uniqueModel.clear()
323-
self.geomCombo.clear()
324-
return
306+
c = None
307+
try:
308+
c = connector._execute(None, sql)
309+
cols = connector._get_cursor_columns(c)
310+
for col in cols:
311+
quotedCols.append(connector.quoteId(col))
325312

326-
finally:
327-
if c:
328-
c.close()
329-
del c
313+
except BaseError as e:
314+
DlgDbError.showError(e, self)
315+
self.uniqueModel.clear()
316+
self.geomCombo.clear()
317+
return
330318

331-
self.setColumnCombos(cols, quotedCols)
319+
finally:
320+
if c:
321+
c.close()
322+
del c
332323

333-
QApplication.restoreOverrideCursor()
324+
self.setColumnCombos(cols, quotedCols)
334325

335326
def setColumnCombos(self, cols, quotedCols):
336327
# 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)

‎python/plugins/db_manager/dlg_table_properties.py

Lines changed: 46 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
from qgis.PyQt.QtCore import Qt, pyqtSignal
2727
from qgis.PyQt.QtWidgets import QDialog, QMessageBox, QApplication
2828

29+
from qgis.utils import OverrideCursor
30+
2931
from .db_plugins.data_model import TableFieldsModel, TableConstraintsModel, TableIndexesModel
3032
from .db_plugins.plugin import BaseError
3133
from .dlg_db_error import DlgDbError
@@ -116,17 +118,14 @@ def addColumn(self):
116118
return
117119
fld = dlg.getField()
118120

119-
QApplication.setOverrideCursor(Qt.WaitCursor)
120-
self.aboutToChangeTable.emit()
121-
try:
122-
# add column to table
123-
self.table.addField(fld)
124-
self.refresh()
125-
except BaseError as e:
126-
DlgDbError.showError(e, self)
127-
return
128-
finally:
129-
QApplication.restoreOverrideCursor()
121+
with OverrideCursor(Qt.WaitCursor):
122+
self.aboutToChangeTable.emit()
123+
try:
124+
# add column to table
125+
self.table.addField(fld)
126+
self.refresh()
127+
except BaseError as e:
128+
DlgDbError.showError(e, self)
130129

131130
def addGeometryColumn(self):
132131
""" open dialog to add geometry column """
@@ -151,16 +150,13 @@ def editColumn(self):
151150
return
152151
new_fld = dlg.getField(True)
153152

154-
QApplication.setOverrideCursor(Qt.WaitCursor)
155-
self.aboutToChangeTable.emit()
156-
try:
157-
fld.update(new_fld.name, new_fld.type2String(), new_fld.notNull, new_fld.default2String())
158-
self.refresh()
159-
except BaseError as e:
160-
DlgDbError.showError(e, self)
161-
return
162-
finally:
163-
QApplication.restoreOverrideCursor()
153+
with OverrideCursor(Qt.WaitCursor):
154+
self.aboutToChangeTable.emit()
155+
try:
156+
fld.update(new_fld.name, new_fld.type2String(), new_fld.notNull, new_fld.default2String())
157+
self.refresh()
158+
except BaseError as e:
159+
DlgDbError.showError(e, self)
164160

165161
def deleteColumn(self):
166162
""" delete currently selected column """
@@ -176,16 +172,13 @@ def deleteColumn(self):
176172
if res != QMessageBox.Yes:
177173
return
178174

179-
QApplication.setOverrideCursor(Qt.WaitCursor)
180-
self.aboutToChangeTable.emit()
181-
try:
182-
fld.delete()
183-
self.refresh()
184-
except BaseError as e:
185-
DlgDbError.showError(e, self)
186-
return
187-
finally:
188-
QApplication.restoreOverrideCursor()
175+
with OverrideCursor(Qt.WaitCursor):
176+
self.aboutToChangeTable.emit()
177+
try:
178+
fld.delete()
179+
self.refresh()
180+
except BaseError as e:
181+
DlgDbError.showError(e, self)
189182

190183
def populateConstraints(self):
191184
constraints = self.table.constraints()
@@ -231,16 +224,13 @@ def deleteConstraint(self):
231224
if res != QMessageBox.Yes:
232225
return
233226

234-
QApplication.setOverrideCursor(Qt.WaitCursor)
235-
self.aboutToChangeTable.emit()
236-
try:
237-
constr.delete()
238-
self.refresh()
239-
except BaseError as e:
240-
DlgDbError.showError(e, self)
241-
return
242-
finally:
243-
QApplication.restoreOverrideCursor()
227+
with OverrideCursor(Qt.WaitCursor):
228+
self.aboutToChangeTable.emit()
229+
try:
230+
constr.delete()
231+
self.refresh()
232+
except BaseError as e:
233+
DlgDbError.showError(e, self)
244234

245235
def currentConstraint(self):
246236
""" returns row index of selected index """
@@ -291,17 +281,14 @@ def createSpatialIndex(self):
291281
return
292282

293283
# TODO: first check whether the index doesn't exist already
294-
QApplication.setOverrideCursor(Qt.WaitCursor)
295-
self.aboutToChangeTable.emit()
296-
297-
try:
298-
self.table.createSpatialIndex()
299-
self.refresh()
300-
except BaseError as e:
301-
DlgDbError.showError(e, self)
302-
return
303-
finally:
304-
QApplication.restoreOverrideCursor()
284+
with OverrideCursor(Qt.WaitCursor):
285+
self.aboutToChangeTable.emit()
286+
287+
try:
288+
self.table.createSpatialIndex()
289+
self.refresh()
290+
except BaseError as e:
291+
DlgDbError.showError(e, self)
305292

306293
def currentIndex(self):
307294
""" returns row index of selected index """
@@ -326,13 +313,10 @@ def deleteIndex(self):
326313
if res != QMessageBox.Yes:
327314
return
328315

329-
QApplication.setOverrideCursor(Qt.WaitCursor)
330-
self.aboutToChangeTable.emit()
331-
try:
332-
idx.delete()
333-
self.refresh()
334-
except BaseError as e:
335-
DlgDbError.showError(e, self)
336-
return
337-
finally:
338-
QApplication.restoreOverrideCursor()
316+
with OverrideCursor(Qt.WaitCursor):
317+
self.aboutToChangeTable.emit()
318+
try:
319+
idx.delete()
320+
self.refresh()
321+
except BaseError as e:
322+
DlgDbError.showError(e, self)

‎python/plugins/db_manager/info_viewer.py

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
from qgis.PyQt.QtCore import Qt
2525
from qgis.PyQt.QtWidgets import QTextBrowser, QApplication
26+
from qgis.utils import OverrideCursor
2627

2728
from .db_plugins.plugin import BaseError, DbError, DBPlugin, Schema, Table
2829
from .dlg_db_error import DlgDbError
@@ -47,15 +48,12 @@ def _linkClicked(self, url):
4748
return
4849

4950
if url.scheme() == "action":
50-
QApplication.setOverrideCursor(Qt.WaitCursor)
51-
try:
52-
if self.item.runAction(url.path()):
53-
self.refresh()
54-
except BaseError as e:
55-
DlgDbError.showError(e, self)
56-
return
57-
finally:
58-
QApplication.restoreOverrideCursor()
51+
with OverrideCursor(Qt.WaitCursor):
52+
try:
53+
if self.item.runAction(url.path()):
54+
self.refresh()
55+
except BaseError as e:
56+
DlgDbError.showError(e, self)
5957

6058
def refresh(self):
6159
self.setDirty(True)

‎python/plugins/db_manager/layer_preview.py

Lines changed: 39 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
from qgis.gui import QgsMapCanvas, QgsMessageBar
2828
from qgis.core import QgsVectorLayer, QgsProject, QgsSettings
29+
from qgis.utils import OverrideCursor
2930

3031
from .db_plugins.plugin import Table
3132

@@ -89,45 +90,44 @@ def _clear(self):
8990

9091
def _loadTablePreview(self, table, limit=False):
9192
""" if has geometry column load to map canvas """
92-
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
93-
self.freeze()
94-
vl = None
95-
96-
if table and table.geomType:
97-
# limit the query result if required
98-
if limit and table.rowCount > 1000:
99-
uniqueField = table.getValidQgisUniqueFields(True)
100-
if uniqueField is None:
101-
self.parent.tabs.setCurrentWidget(self.parent.info)
102-
self.parent.infoBar.pushMessage(
103-
QApplication.translate("DBManagerPlugin", "Unable to find a valid unique field"),
104-
QgsMessageBar.WARNING, self.parent.iface.messageTimeout())
105-
return
106-
107-
uri = table.database().uri()
108-
uri.setDataSource("", u"(SELECT * FROM %s LIMIT 1000)" % table.quotedName(), table.geomColumn, "",
109-
uniqueField.name)
110-
provider = table.database().dbplugin().providerName()
111-
vl = QgsVectorLayer(uri.uri(False), table.name, provider)
93+
with OverrideCursor(Qt.WaitCursor):
94+
self.freeze()
95+
vl = None
96+
97+
if table and table.geomType:
98+
# limit the query result if required
99+
if limit and table.rowCount > 1000:
100+
uniqueField = table.getValidQgisUniqueFields(True)
101+
if uniqueField is None:
102+
self.parent.tabs.setCurrentWidget(self.parent.info)
103+
self.parent.infoBar.pushMessage(
104+
QApplication.translate("DBManagerPlugin", "Unable to find a valid unique field"),
105+
QgsMessageBar.WARNING, self.parent.iface.messageTimeout())
106+
return
107+
108+
uri = table.database().uri()
109+
uri.setDataSource("", u"(SELECT * FROM %s LIMIT 1000)" % table.quotedName(), table.geomColumn, "",
110+
uniqueField.name)
111+
provider = table.database().dbplugin().providerName()
112+
vl = QgsVectorLayer(uri.uri(False), table.name, provider)
113+
else:
114+
vl = table.toMapLayer()
115+
116+
if not vl.isValid():
117+
vl.deleteLater()
118+
vl = None
119+
120+
# remove old layer (if any) and set new
121+
if self.currentLayer:
122+
QgsProject.instance().removeMapLayers([self.currentLayer.id()])
123+
124+
if vl:
125+
self.setLayers([vl])
126+
QgsProject.instance().addMapLayers([vl], False)
127+
self.zoomToFullExtent()
112128
else:
113-
vl = table.toMapLayer()
129+
self.setLayers([])
114130

115-
if not vl.isValid():
116-
vl.deleteLater()
117-
vl = None
131+
self.currentLayer = vl
118132

119-
# remove old layer (if any) and set new
120-
if self.currentLayer:
121-
QgsProject.instance().removeMapLayers([self.currentLayer.id()])
122-
123-
if vl:
124-
self.setLayers([vl])
125-
QgsProject.instance().addMapLayers([vl], False)
126-
self.zoomToFullExtent()
127-
else:
128-
self.setLayers([])
129-
130-
self.currentLayer = vl
131-
132-
self.freeze(False)
133-
QApplication.restoreOverrideCursor()
133+
self.freeze(False)

‎python/plugins/db_manager/table_viewer.py

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
from qgis.PyQt.QtWidgets import QTableView, QAbstractItemView, QApplication, QAction
2525
from qgis.PyQt.QtGui import QKeySequence, QCursor, QClipboard
2626

27+
from qgis.utils import OverrideCursor
28+
2729
from .db_plugins.plugin import DbError, Table
2830
from .dlg_db_error import DlgDbError
2931

@@ -86,20 +88,14 @@ def _clear(self):
8688
model.deleteLater()
8789

8890
def _loadTableData(self, table):
89-
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
90-
try:
91-
# set the new model
92-
self.setModel(table.tableDataModel(self))
93-
94-
except DbError as e:
95-
DlgDbError.showError(e, self)
96-
return
97-
98-
else:
99-
self.update()
100-
101-
finally:
102-
QApplication.restoreOverrideCursor()
91+
with OverrideCursor(Qt.WaitCursor):
92+
try:
93+
# set the new model
94+
self.setModel(table.tableDataModel(self))
95+
except DbError as e:
96+
DlgDbError.showError(e, self)
97+
else:
98+
self.update()
10399

104100
def copySelectedResults(self):
105101
if len(self.selectedIndexes()) <= 0:

‎python/plugins/processing/algs/qgis/ui/FieldsCalculatorDialog.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
QgsMapLayerProxyModel,
4141
QgsMessageLog)
4242
from qgis.gui import QgsEncodingFileDialog
43+
from qgis.utils import OverrideCursor
4344

4445
from processing.core.ProcessingConfig import ProcessingConfig
4546
from processing.core.ProcessingLog import ProcessingLog
@@ -220,10 +221,9 @@ def getParamValues(self):
220221

221222
def accept(self):
222223
keepOpen = ProcessingConfig.getSetting(ProcessingConfig.KEEP_DIALOG_OPEN)
223-
try:
224-
parameters = self.getParamValues()
225-
if parameters:
226-
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
224+
parameters = self.getParamValues()
225+
if parameters:
226+
with OverrideCursor(Qt.WaitCursor):
227227
context = dataobjects.createContext()
228228
ProcessingLog.addToLog(self.alg.asPythonCommand(parameters, context))
229229

@@ -235,8 +235,6 @@ def accept(self):
235235
not keepOpen)
236236
if not keepOpen:
237237
QDialog.reject(self)
238-
finally:
239-
QApplication.restoreOverrideCursor()
240238

241239
def reject(self):
242240
self.executed = False

‎python/plugins/processing/gui/ConfigDialog.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
QgsSpinBox,
5252
QgsOptionsPageWidget)
5353
from qgis.core import NULL, QgsApplication, QgsSettings
54+
from qgis.utils import OverrideCursor
5455

5556
from processing.core.ProcessingConfig import (ProcessingConfig,
5657
settingsWatcher,
@@ -293,10 +294,9 @@ def accept(self):
293294
return
294295
setting.save(qsettings)
295296

296-
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
297-
for p in QgsApplication.processingRegistry().providers():
298-
p.refreshAlgorithms()
299-
QApplication.restoreOverrideCursor()
297+
with OverrideCursor(Qt.WaitCursor):
298+
for p in QgsApplication.processingRegistry().providers():
299+
p.refreshAlgorithms()
300300

301301
settingsWatcher.settingsChanged.emit()
302302

‎python/plugins/processing/gui/GetScriptsAndModels.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ def popupError(self, error=None, url=None):
165165

166166
def grabHTTP(self, url, loadFunction, arguments=None):
167167
"""Grab distant content via QGIS internal classes and QtNetwork."""
168-
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
168+
QApplication.setOverrideCursor(Qt.WaitCursor)
169169
request = QUrl(url)
170170
reply = self.manager.get(QNetworkRequest(request))
171171
if arguments:

‎python/plugins/processing/gui/ScriptEditorDialog.py

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
QApplication)
3939

4040
from qgis.core import QgsApplication, QgsSettings
41-
from qgis.utils import iface
41+
from qgis.utils import iface, OverrideCursor
4242

4343
from processing.gui.AlgorithmDialog import AlgorithmDialog
4444
from processing.gui.HelpEditionDialog import HelpEditionDialog
@@ -207,15 +207,14 @@ def openScript(self):
207207
if self.filename == '':
208208
return
209209

210-
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
211-
with codecs.open(self.filename, 'r', encoding='utf-8') as f:
212-
txt = f.read()
210+
with OverrideCursor(Qt.WaitCursor):
211+
with codecs.open(self.filename, 'r', encoding='utf-8') as f:
212+
txt = f.read()
213213

214-
self.editor.setText(txt)
215-
self.hasChanged = False
216-
self.editor.setModified(False)
217-
self.editor.recolor()
218-
QApplication.restoreOverrideCursor()
214+
self.editor.setText(txt)
215+
self.hasChanged = False
216+
self.editor.setModified(False)
217+
self.editor.recolor()
219218

220219
def save(self):
221220
self.saveScript(False)

‎python/utils.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -625,9 +625,32 @@ def spatialite_connect(*args, **kwargs):
625625
return dbapi2.connect(*args, **kwargs)
626626

627627

628+
class OverrideCursor():
629+
"""
630+
Executes a code block with a different cursor set and makes sure the cursor
631+
is restored even if exceptions are raised or an intermediate ``return``
632+
statement is hit.
633+
634+
Example:
635+
```
636+
with OverrideCursor(Qt.WaitCursor):
637+
do_a_slow(operation)
638+
```
639+
"""
640+
641+
def __init__(self, cursor):
642+
self.cursor = cursor
643+
644+
def __enter__(self):
645+
QApplication.setOverrideCursor(self.cursor)
646+
647+
def __exit__(self, exc_type, exc_val, exc_tb):
648+
QApplication.restoreOverrideCursor()
649+
628650
#######################
629651
# IMPORT wrapper
630652

653+
631654
_uses_builtins = True
632655
try:
633656
import builtins

0 commit comments

Comments
 (0)
Please sign in to comment.