You can use the following approach which is to make use of the setExceptedLayerList() method of QgsMapLayerComboBox
and pass a list of layers which will not be shown in the combo box.
The basic logic to create the excepted list which will exclude any layer which is not a point layer and does not contain your specific field is like this:
self.map_layers = QgsProject.instance().mapLayers().values()
self.allow_list = [
lyr.id() for lyr in self.map_layers if lyr.type() == QgsMapLayerType.VectorLayer
and lyr.geometryType() == QgsWkbTypes.PointGeometry
and 'Vessel' in [f.name() for f in lyr.fields()]
]
self.except_list = [l for l in self.map_layers if l.id() not in self.allow_list]
self.dlg.mMapLayerComboBox.setExceptedLayerList(self.except_list)
In a plugin, I would place this logic inside a class method and call it when the dialog is shown. I would also connect this method to a signal such as QgsMapCanvas.layersChanged
which, in your plugin would look something like:
self.iface.mapCanvas().layersChanged.connect(self.populateComboBox)
This will ensure that the layers shown in the map layer combo box are updated when the layer set changes, even if the plugin dialog is still open. For example when adding/removing layers in the current project or open a new or existing project. You could also add a condition here to check if the dialog is actually open, to avoid unnecessary overhead slowing things down. Just make sure this signal/ slot is only connected once, when the plugin is initialised.
Below you will find a very simple example plugin based on the minimal plugin example from Martin Dobias here.
I have tested this plugin which should show you how to set up the logic I have described above.
from PyQt5.QtWidgets import QDialog, QAction, QVBoxLayout, QPushButton, QMessageBox
from qgis.core import QgsMapLayerProxyModel, QgsProject, QgsMapLayerType, QgsWkbTypes
from qgis.gui import QgsMapLayerComboBox
def classFactory(iface):
return MinimalPlugin(iface)
class MinimalPlugin:
def __init__(self, iface):
self.iface = iface
self.dlg = testPluginDialog()
def initGui(self):
self.action = QAction('Go!', self.iface.mainWindow())
self.action.triggered.connect(self.showDialog)
self.iface.addToolBarIcon(self.action)
self.dlg.btn.clicked.connect(self.run)
self.iface.mapCanvas().layersChanged.connect(self.populateComboBox)
def unload(self):
self.iface.removeToolBarIcon(self.action)
del self.action
def showDialog(self):
self.dlg.show()
self.populateComboBox()
def populateComboBox(self):
if self.dlg.isVisible():
self.map_layers = QgsProject.instance().mapLayers().values()
self.allow_list = [
lyr.id() for lyr in self.map_layers if lyr.type() == QgsMapLayerType.VectorLayer
and lyr.geometryType()== QgsWkbTypes.PointGeometry
and 'Vessel' in [f.name() for f in lyr.fields()]
]
self.except_list = [l for l in self.map_layers if l.id() not in self.allow_list]
self.dlg.mMapLayerComboBox.setExceptedLayerList(self.except_list)
def run(self):
QMessageBox.information(None, 'Minimal plugin', self.dlg.mMapLayerComboBox.currentLayer().name())
class testPluginDialog(QDialog):
def __init__(self):
QDialog.__init__(self)
self.setGeometry(150, 150, 500, 350)
self.layout = QVBoxLayout()
self.mMapLayerComboBox = QgsMapLayerComboBox(self)
self.btn = QPushButton('Run', self)
self.layout.addWidget(self.mMapLayerComboBox)
self.layout.addWidget(self.btn)
self.setLayout(self.layout)