2424
2525from PyQt4 .QtCore import Qt , QObject , QSettings , QByteArray , SIGNAL , pyqtSignal
2626from PyQt4 .QtGui import QDialog , QWidget , QAction , QKeySequence , \
27- QDialogButtonBox , QApplication , QCursor , QMessageBox , QClipboard , QInputDialog , QIcon
27+ QDialogButtonBox , QApplication , QCursor , QMessageBox , QClipboard , QInputDialog , QIcon , QStyledItemDelegate , QStandardItemModel , QStandardItem
2828from PyQt4 .Qsci import QsciAPIs
2929
3030from qgis .core import QgsProject
@@ -80,6 +80,15 @@ def __init__(self, iface, db, parent=None):
8080
8181 self .updatePresetsCombobox ()
8282
83+ self .uniqueCombo .setItemDelegate (QStyledItemDelegate ())
84+ self .uniqueModel = QStandardItemModel (self .uniqueCombo )
85+ self .uniqueCombo .setModel (self .uniqueModel )
86+ self .uniqueCombo .setEditable (True )
87+ self .uniqueCombo .lineEdit ().setReadOnly (True )
88+ self .uniqueModel .itemChanged .connect (self .uniqueChanged ) # react to the (un)checking of an item
89+ self .uniqueCombo .lineEdit ().textChanged .connect (self .uniqueTextChanged ) # there are other events that change the displayed text and some of them can not be caught directly
90+ self .uniqueChanged
91+
8392 # hide the load query as layer if feature is not supported
8493 self ._loadAsLayerAvailable = self .db .connector .hasCustomQuerySupport ()
8594 self .loadAsLayerGroup .setVisible (self ._loadAsLayerAvailable )
@@ -161,29 +170,38 @@ def executeSql(self):
161170 if old_model :
162171 old_model .deleteLater ()
163172
173+ cols = []
174+ quotedCols = []
175+
164176 try :
165177 # set the new model
166178 model = self .db .sqlResultModel (sql , self )
167179 self .viewResult .setModel (model )
168180 self .lblResult .setText (self .tr ("%d rows, %.1f seconds" ) % (model .affectedRows (), model .secs ()))
181+ cols = self .viewResult .model ().columnNames ()
182+ for col in cols :
183+ quotedCols .append (self .db .connector .quoteId (col ))
169184
170185 except BaseError as e :
171186 QApplication .restoreOverrideCursor ()
172187 DlgDbError .showError (e , self )
173- self .uniqueCombo .clear ()
188+ self .uniqueModel .clear ()
174189 self .geomCombo .clear ()
175190 return
176191
177- cols = self .viewResult .model ().columnNames ()
178- self .setColumnCombos (cols )
192+ self .setColumnCombos (cols , quotedCols )
179193
180194 self .update ()
181195 QApplication .restoreOverrideCursor ()
182196
183197 def loadSqlLayer (self ):
184198 hasUniqueField = self .uniqueColumnCheck .checkState () == Qt .Checked
185199 if hasUniqueField :
186- uniqueFieldName = self .uniqueCombo .currentText ()
200+ checkedCols = []
201+ for item in self .uniqueModel .findItems ("*" , Qt .MatchWildcard ):
202+ if item .checkState () == Qt .Checked :
203+ checkedCols .append (item .data ())
204+ uniqueFieldName = "," .join (checkedCols )
187205 else :
188206 uniqueFieldName = None
189207 hasGeomCol = self .hasGeometryCol .checkState () == Qt .Checked
@@ -250,18 +268,21 @@ def fillColumnCombos(self):
250268
251269 # get all the columns
252270 cols = []
271+ quotedCols = []
253272 connector = self .db .connector
254273 sql = u"SELECT * FROM (%s\n ) AS %s LIMIT 0" % (unicode (query ), connector .quoteId (alias ))
255274
256275 c = None
257276 try :
258277 c = connector ._execute (None , sql )
259278 cols = connector ._get_cursor_columns (c )
279+ for col in cols :
280+ quotedCols .append (connector .quoteId (col ))
260281
261282 except BaseError as e :
262283 QApplication .restoreOverrideCursor ()
263284 DlgDbError .showError (e , self )
264- self .uniqueCombo .clear ()
285+ self .uniqueModel .clear ()
265286 self .geomCombo .clear ()
266287 return
267288
@@ -270,11 +291,11 @@ def fillColumnCombos(self):
270291 c .close ()
271292 del c
272293
273- self .setColumnCombos (cols )
294+ self .setColumnCombos (cols , quotedCols )
274295
275296 QApplication .restoreOverrideCursor ()
276297
277- def setColumnCombos (self , cols ):
298+ def setColumnCombos (self , cols , quotedCols ):
278299 # get sensible default columns. do this before sorting in case there's hints in the column order (eg, id is more likely to be first)
279300 try :
280301 defaultGeomCol = next (col for col in cols if col in ['geom' , 'geometry' , 'the_geom' , 'way' ])
@@ -285,10 +306,22 @@ def setColumnCombos(self, cols):
285306 except :
286307 defaultUniqueCol = None
287308
288- cols .sort ()
289- self .uniqueCombo .clear ()
309+ colNames = zip (cols , quotedCols )
310+ colNames .sort ()
311+ newItems = []
312+ for (col , quotedCol ) in colNames :
313+ item = QStandardItem (col )
314+ item .setData (quotedCol )
315+ item .setEnabled (True )
316+ item .setCheckable (True )
317+ item .setSelectable (False )
318+ item .setCheckState (Qt .Unchecked )
319+ newItems .append (item )
320+ self .uniqueModel .clear ()
321+ self .uniqueModel .appendColumn (newItems )
322+ self .uniqueChanged ()
323+
290324 self .geomCombo .clear ()
291- self .uniqueCombo .addItems (cols )
292325 self .geomCombo .addItems (cols )
293326
294327 # set sensible default columns
@@ -297,7 +330,9 @@ def setColumnCombos(self, cols):
297330 except :
298331 pass
299332 try :
300- self .uniqueCombo .setCurrentIndex (cols .index (defaultUniqueCol ))
333+ items = self .uniqueModel .findItems (defaultUniqueCol )
334+ if items :
335+ items [0 ].setCheckState (Qt .Checked )
301336 except :
302337 pass
303338
@@ -356,3 +391,17 @@ def _getSqlQuery(self):
356391 if len (sql ) == 0 :
357392 sql = self .editSql .text ()
358393 return sql
394+
395+ def uniqueChanged (self ):
396+ # when an item is (un)checked, simply trigger an update of the combobox text
397+ self .uniqueTextChanged (None )
398+
399+ def uniqueTextChanged (self , text ):
400+ # Whenever there is new text displayed in the combobox, check if it is the correct one and if not, display the correct one.
401+ checkedItems = []
402+ for item in self .uniqueModel .findItems ("*" , Qt .MatchWildcard ):
403+ if item .checkState () == Qt .Checked :
404+ checkedItems .append (item .text ())
405+ label = ", " .join (checkedItems )
406+ if text != label :
407+ self .uniqueCombo .setEditText (label )
0 commit comments