Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge branch 'DbManager_SetFilter' of https://github.com/SebDieBln/QGIS
[DbManager] New button to define a sql-filter when adding a query-based layer
  • Loading branch information
brushtyler committed Nov 29, 2015
2 parents df30571 + f6e3161 commit 5408e84
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 22 deletions.
4 changes: 2 additions & 2 deletions python/plugins/db_manager/db_plugins/oracle/plugin.py
Expand Up @@ -197,13 +197,13 @@ def sqlResultModel(self, sql, parent):

def toSqlLayer(self, sql, geomCol, uniqueCol,
layerName=u"QueryLayer", layerType=None,
avoidSelectById=False):
avoidSelectById=False, filter=""):
from qgis.core import QgsMapLayer, QgsVectorLayer

uri = self.uri()
con = self.database().connector

uri.setDataSource(u"", u"({})".format(sql), geomCol, u"", uniqueCol)
uri.setDataSource(u"", u"({})".format(sql), geomCol, filter, uniqueCol)
if avoidSelectById:
uri.disableSelectAtId(True)
provider = self.dbplugin().providerName()
Expand Down
4 changes: 2 additions & 2 deletions python/plugins/db_manager/db_plugins/plugin.py
Expand Up @@ -260,7 +260,7 @@ def uniqueIdFunction(self):
# may be overloaded by derived classes
return "row_number() over ()"

def toSqlLayer(self, sql, geomCol, uniqueCol, layerName="QueryLayer", layerType=None, avoidSelectById=False):
def toSqlLayer(self, sql, geomCol, uniqueCol, layerName="QueryLayer", layerType=None, avoidSelectById=False, filter=""):
from qgis.core import QgsMapLayer, QgsVectorLayer, QgsRasterLayer

if uniqueCol is None:
Expand All @@ -274,7 +274,7 @@ def toSqlLayer(self, sql, geomCol, uniqueCol, layerName="QueryLayer", layerType=
uniqueCol = "_uid_"

uri = self.uri()
uri.setDataSource("", u"(%s\n)" % sql, geomCol, "", uniqueCol)
uri.setDataSource("", u"(%s\n)" % sql, geomCol, filter, uniqueCol)
if avoidSelectById:
uri.disableSelectAtId(True)
provider = self.dbplugin().providerName()
Expand Down
44 changes: 38 additions & 6 deletions python/plugins/db_manager/dlg_sql_window.py
Expand Up @@ -54,6 +54,7 @@ def __init__(self, iface, db, parent=None):
QWidget.__init__(self, parent)
self.iface = iface
self.db = db
self.filter = ""
self.allowMultiColumnPk = isinstance(db, PGDatabase) # at the moment only PostGIS allows a primary key to span multiple columns, spatialite doesn't
self.setupUi(self)
self.setWindowTitle(
Expand All @@ -78,6 +79,7 @@ def __init__(self, iface, db, parent=None):
copyAction.triggered.connect(self.copySelectedResults)

self.btnExecute.clicked.connect(self.executeSql)
self.btnSetFilter.clicked.connect(self.setFilter)
self.btnClear.clicked.connect(self.clearSql)

self.presetStore.clicked.connect(self.storePreset)
Expand Down Expand Up @@ -167,6 +169,7 @@ def loadAsLayerToggled(self, checked):
def clearSql(self):
self.editSql.clear()
self.editSql.setFocus()
self.filter = ""

def executeSql(self):

Expand Down Expand Up @@ -206,7 +209,7 @@ def executeSql(self):
self.update()
QApplication.restoreOverrideCursor()

def loadSqlLayer(self):
def _getSqlLayer(self):
hasUniqueField = self.uniqueColumnCheck.checkState() == Qt.Checked
if hasUniqueField:
if self.allowMultiColumnPk:
Expand All @@ -229,14 +232,12 @@ def loadSqlLayer(self):

query = self._getSqlQuery()
if query == "":
return
return None

# remove a trailing ';' from query if present
if query.strip().endswith(';'):
query = query.strip()[:-1]

QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))

from qgis.core import QgsMapLayer, QgsMapLayerRegistry

layerType = QgsMapLayer.VectorLayer if self.vectorRadio.isChecked() else QgsMapLayer.RasterLayer
Expand All @@ -257,10 +258,23 @@ def loadSqlLayer(self):

# create the layer
layer = self.db.toSqlLayer(query, geomFieldName, uniqueFieldName, newLayerName, layerType,
self.avoidSelectById.isChecked())
self.avoidSelectById.isChecked(), self.filter)
if layer.isValid():
QgsMapLayerRegistry.instance().addMapLayers([layer], True)
return layer
else:
return None

def loadSqlLayer(self):
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
layer = self._getSqlLayer()
QApplication.restoreOverrideCursor()

if layer == None:
return

from qgis.core import QgsMapLayerRegistry
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
QgsMapLayerRegistry.instance().addMapLayers([layer], True)
QApplication.restoreOverrideCursor()

def fillColumnCombos(self):
Expand Down Expand Up @@ -443,3 +457,21 @@ def uniqueTextChanged(self, text):
label = ", ".join(checkedItems)
if text != label:
self.uniqueCombo.setEditText(label)

def setFilter(self):
from qgis.gui import QgsQueryBuilder
layer = self._getSqlLayer()

if layer == None:
# probably the defined filter does not work for the query, so try to create the layer without the filter
filter = self.filter
self.filter = ""
layer = self._getSqlLayer()
self.filter = filter
if layer == None:
return

dlg = QgsQueryBuilder(layer)
dlg.setSql(self.filter)
if dlg.exec_():
self.filter = dlg.sql()
67 changes: 55 additions & 12 deletions python/plugins/db_manager/ui/DlgSqlWindow.ui
Expand Up @@ -38,6 +38,40 @@
<property name="margin">
<number>0</number>
</property>
<item row="2" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QCheckBox" name="avoidSelectById">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Avoid selecting feature by id. Sometimes - especially when running expensive queries/views - fetching the data sequentially instead of fetching features by id can be much quicker.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Avoid selecting by feature id</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="loadLayerBtn">
<property name="text">
<string>Load now!</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
Expand Down Expand Up @@ -203,9 +237,12 @@ columns</string>
</widget>
</item>
<item>
<widget class="QPushButton" name="loadLayerBtn">
<widget class="QPushButton" name="btnSetFilter">
<property name="text">
<string>Load now!</string>
<string>Set filter</string>
</property>
<property name="autoDefault">
<bool>false</bool>
</property>
</widget>
</item>
Expand All @@ -214,16 +251,6 @@ columns</string>
</layout>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="avoidSelectById">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Avoid selecting feature by id. Sometimes - especially when running expensive queries/views - fetching the data sequentially instead of fetching features by id can be much quicker.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Avoid selecting by feature id</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
Expand Down Expand Up @@ -435,5 +462,21 @@ columns</string>
</hint>
</hints>
</connection>
<connection>
<sender>loadAsLayerGroup</sender>
<signal>toggled(bool)</signal>
<receiver>loadAsLayerWidget</receiver>
<slot>setVisible(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>312</x>
<y>450</y>
</hint>
<hint type="destinationlabel">
<x>312</x>
<y>456</y>
</hint>
</hints>
</connection>
</connections>
</ui>

0 comments on commit 5408e84

Please sign in to comment.