2

I'm developing plugin where I want to be able to edit non-spatial table inside the attribute table dialogue. As it seems that the only way to do so is to add this table to the TOC first, I do so. But it is pointless to keep this table inside the TOC after the editing is done and the attribute table is closed. I would like to remove table from TOC right after the attribute window is closed. Is there a way to catch the signal from the showAttributeTable() when it is destroyed? Or is there a way not to add table to TOC in the first place?

Here is the code that I use:

def qgisOpenTable(self, layer_name, schema, table, geom_column=None, subset=None):
      '''
      Opens table in QGIS attribute table window
      '''
      uri = QgsDataSourceURI()
      uri.setConnection(self.server, self.port, self.db_name, self.login, self.password)  
      uri.setDataSource(schema, table, geom_column, subset)
      vlayer = QgsVectorLayer(uri.uri(), layer_name, "postgres")
      QgsMapLayerRegistry.instance().addMapLayer(vlayer)
      layer_id = vlayer.id()
      i = iface.showAttributeTable(vlayer)

      # I would like to have something like this:
      i.destroyed.connect(QgsMapLayerRegistry.instance().removeMapLayer(layer_id))

The only workaround that came to my mind is to remove table after some time, but this is suboptimal.

  • Did u solve your problem ? – snaileater Jun 20 '15 at 11:27
  • @snaileater, I'm using a temporary workaround (pop a button in the QmessageBar to delete layer afterwards), though I was unable to find way to do delete table automatically. – SS_Rebelious Jun 22 '15 at 14:21
2

Rebelious,
here is what i did to solve your question (maybe not the smarter solution but working "automatically" at least ...) :

from PyQt4.QtCore import QObject,QTimer
from PyQt4.QtGui import *

import re

class Test():

    openedTables=[]

    def main(self):
        QApplication.instance().focusChanged.connect(self.monitor)

    def monitor(self,qa,qb):
        if qa is None:
            #print('qa=None...')
            QTimer().singleShot(100,self.timer)

        if qb is not None:
            if qb.objectName()=="mToggleEditingButton":
                tableName=re.search(r'- (\S*) ::',qb.parent().windowTitle()).group(1)
                if tableName not in self.openedTables:
                    self.openedTables.append(tableName)

    def timer(self):
        for i in self.openedTables:
                if self.checkTable(i)==False :
                    layer=QgsMapLayerRegistry.instance().mapLayersByName(i)[0]
                    if not layer.hasGeometryType():
                        print('closing table : ' + str(i))
                        self.openedTables.remove(i)
                        QgsMapLayerRegistry.instance().removeMapLayer(layer.id())

    def checkTable(self,string):
        # allWidgets / topLevelWidgets
        l=QApplication.instance().topLevelWidgets()
        bool=False
        for i in l:
            if i.objectName()=='QgsAttributeTableDialog':
                layerName=re.search(r'- (\S*) ::',i.windowTitle()).group(1)
                if layerName ==string:
                    bool=True
        return bool

The idea is to use the focusChanged signal of Qapplication.instance() and to record any attributeTable openings and then check table closings ...
I had to use a QTimer because when i enter the slot ("monitor") the Attribute Table loose focus but is not considered as closed yet ...

So using a timer is the only solution i found ...
There's surely a smarter way to do that ...
Hope it helps anyway !

  • Very interesting. But it isn't clear to me how to use it. Should I just call the Test() class before opening attribute table? Please rewrite code in the context of my example. – SS_Rebelious Jun 27 '15 at 17:34
  • yes call the Test() class and then any attributeTable closing will close the table itself (as long as it isn't a geographic table, that was what u were asking i think). If u have any question ask me ... – snaileater Jul 1 '15 at 7:03
  • Did it solve your question Rebelious ? – snaileater Jul 11 '15 at 9:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.