UPDATE: Pasted the whole code.
I am developing a QGS project and im in the process of removing menus and grouping the plugins I have created (using PluginBuilder). So far I have 3 plugins and I want to group them in a single Tools menu.
This question might have been answered already by the post Adding multiple plugins to custom menu in QGIS but it doesn't seem to work though I copied the whole code in the answer. I get the error "AttributeError: FindFarm instance has no attribute 'action' " Below is my code in my plugin:
# -*- coding: utf-8 -*-
"""
/***************************************************************************
FindFarm
A QGIS plugin
Find and zoom to a farm
-------------------
begin : 2017-09-29
git sha : $Format:%H$
copyright : (C) 2017 by William Ernesto Jr
email : williamcernestojr@yahoo.com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
"""
from PyQt4.QtCore import QSettings, QTranslator, qVersion, QCoreApplication
from PyQt4.QtGui import *
# Initialize Qt resources from file resources.py
import resources
# Import the code for the dialog
from find_farm_dialog import FindFarmDialog
from qgis.core import *
import os.path
class FindFarm:
"""QGIS Plugin Implementation."""
def __init__(self, iface):
"""Constructor.
:param iface: An interface instance that will be passed to this class
which provides the hook by which you can manipulate the QGIS
application at run time.
:type iface: QgsInterface
"""
# Save reference to the QGIS interface
self.iface = iface
# initialize plugin directory
self.plugin_dir = os.path.dirname(__file__)
# initialize locale
locale = QSettings().value('locale/userLocale')[0:2]
locale_path = os.path.join(
self.plugin_dir,
'i18n',
'FindFarm_{}.qm'.format(locale))
if os.path.exists(locale_path):
self.translator = QTranslator()
self.translator.load(locale_path)
if qVersion() > '4.3.3':
QCoreApplication.installTranslator(self.translator)
# Create the dialog (after translation) and keep reference
self.dlg = FindFarmDialog()
# Declare instance attributes
self.actions = []
self.menu = self.tr(u'&FindFarm')
# TODO: We are going to let the user set this up in a future iteration
self.toolbar = self.iface.addToolBar(u'FindFarm')
self.toolbar.setObjectName(u'FindFarm')
self.iface.mapCanvas().clear()
self.iface.mapCanvas().refresh()
# noinspection PyMethodMayBeStatic
def tr(self, message):
"""Get the translation for a string using Qt translation API.
We implement this ourselves since we do not inherit QObject.
:param message: String for translation.
:type message: str, QString
:returns: Translated version of message.
:rtype: QString
"""
# noinspection PyTypeChecker,PyArgumentList,PyCallByClass
return QCoreApplication.translate('FindFarm', message)
def add_action(
self,
icon_path,
text,
callback,
enabled_flag=True,
add_to_menu=True,
add_to_toolbar=True,
status_tip=None,
whats_this=None,
parent=None):
"""Add a toolbar icon to the toolbar.
:param icon_path: Path to the icon for this action. Can be a resource
path (e.g. ':/plugins/foo/bar.png') or a normal file system path.
:type icon_path: str
:param text: Text that should be shown in menu items for this action.
:type text: str
:param callback: Function to be called when the action is triggered.
:type callback: function
:param enabled_flag: A flag indicating if the action should be enabled
by default. Defaults to True.
:type enabled_flag: bool
:param add_to_menu: Flag indicating whether the action should also
be added to the menu. Defaults to True.
:type add_to_menu: bool
:param add_to_toolbar: Flag indicating whether the action should also
be added to the toolbar. Defaults to True.
:type add_to_toolbar: bool
:param status_tip: Optional text to show in a popup when mouse pointer
hovers over the action.
:type status_tip: str
:param parent: Parent widget for the new action. Defaults None.
:type parent: QWidget
:param whats_this: Optional text to show in the status bar when the
mouse pointer hovers over the action.
:returns: The action that was created. Note that the action is also
added to self.actions list.
:rtype: QAction
"""
# Create the dialog (after translation) and keep reference
self.dlg = FindFarmDialog()
icon = QIcon(icon_path)
action = QAction(icon, text, parent)
action.triggered.connect(callback)
action.setEnabled(enabled_flag)
if status_tip is not None:
action.setStatusTip(status_tip)
if whats_this is not None:
action.setWhatsThis(whats_this)
if add_to_toolbar:
self.toolbar.addAction(action)
if add_to_menu:
self.iface.addPluginToDatabaseMenu(
self.menu,
action)
self.actions.append(action)
return action
def initGui(self):
"""Create the menu entries and toolbar icons inside the QGIS GUI."""
icon_path = ':/plugins/FindFarm/icon.png'
self.add_action(
icon_path,
text=self.tr(u'Find Farm'),
callback=self.run,
parent=self.iface.mainWindow())
# Check if the menu exists and get it
self.menu = self.iface.mainWindow().findChild( QMenu, '&My tools' )
# If the menu does not exist, create it!
if not self.menu:
self.menu = QMenu( '&Tools', self.iface.mainWindow().menuBar() )
self.menu.setObjectName( '&Tools' )
actions = self.iface.mainWindow().menuBar().actions()
lastAction = actions[-1]
self.iface.mainWindow().menuBar().insertMenu( lastAction, self.menu )
# Finally, add your action to the menu
self.menu.addAction( self.action )
def unload(self):
"""Removes the plugin menu item and icon from QGIS GUI."""
for action in self.actions:
self.iface.removePluginDatabaseMenu(
self.tr(u'&FindFarm'),
action)
self.iface.removeToolBarIcon(action)
# remove the toolbar
del self.toolbar
def run(self):
"""Run method that performs all the real work"""
self.iface.mapCanvas().clear()
self.iface.mapCanvas().refresh()
for lyr in QgsMapLayerRegistry.instance().mapLayers().values():
print "Layer is ", lyr.name()
if lyr.name() == "Farm Extents":
layer = lyr
self.iface.setActiveLayer(layer)
farmname = layer.dataProvider().fieldNameIndex( 'ATT_FARM_FieldGrp_CODE' )
uv = layer.dataProvider().uniqueValues( farmname )
self.dlg.comboBox.clear()
self.dlg.comboBox.addItems( uv )
# show the dialog
self.dlg.show()
break
else:
msg = QMessageBox.information(self.iface.mainWindow(), "Error", "Could not find a layer named 'Farm Extents'")
return
# Run the dialog event loop
result = self.dlg.exec_()
# See if OK was pressed
if result:
fname = self.dlg.comboBox.currentText()
QgsExpressionContextUtils.setProjectVariable('farm_name',fname)
#l = self.iface.mapCanvas().layers()['Farm Extents']
expr = QgsExpression( "\"ATT_FARM_FieldGrp_CODE\"='" + fname + "'")
it = layer.getFeatures( QgsFeatureRequest( expr ) )
ids = [i.id() for i in it]
layer.setSelectedFeatures( ids )
self.iface.mapCanvas().zoomToSelected()
print "Zoomed in to", fname
I'm new to python.