[Qgis-developer] Listener for Atlas Change Page
Shawn Tse
shawntse at gmail.com
Sun Dec 25 00:02:41 PST 2016
Hello there,
So I've managed to solve the problem by removing the QObject reference
in the constructor. I'm working on trying to get a message to play
when a composer is added. (My goal is to get it to add a listener for
when the atlas is turned on, and then maybe to draw a line or
something when the feature is changed.)
However, the message does not play when a composer is added. I'm not
sure what I'm doing wrong here. Thanks so much for all the help.
# -*- coding: utf-8 -*-
"""
/***************************************************************************
AtlasProfile
A QGIS plugin
Uses the polygon/polyline atlas features to plot a profile.
-------------------
begin : 2016-12-17
git sha : $Format:%H$
***************************************************************************/
/***************************************************************************
* *
* 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 QAction, QIcon
# Initialize Qt resources from file resources.py
import resources
# Import the code for the dialog
from atlas_profile_dialog import AtlasProfileDialog
import os.path
from qgis.gui import QgsMessageBar
class AtlasProfile:
"""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',
'AtlasProfile_{}.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)
# Declare instance attributes
self.actions = []
self.menu = self.tr(u'&Atlas-based Profile Plotter')
# TODO: We are going to let the user set this up in a future iteration
self.toolbar = self.iface.addToolBar(u'AtlasProfile')
self.toolbar.setObjectName(u'AtlasProfile')
# 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('AtlasProfile', 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 = AtlasProfileDialog()
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.addPluginToMenu(
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/AtlasProfile/icon.png'
self.add_action(
icon_path,
text=self.tr(u'About'),
callback=self.run,
parent=self.iface.mainWindow())
# QgsMessageLog.logMessage("message here", "name there")
self.iface.messageBar().pushMessage("Started
AtlasProfile","AtlasProfile plugin successfully reached this point")
l=AtlasListener()
l.setCompositionListener(self.iface)
# this currently doesn't work. what we need it to do is to run
a listener for when we start a composition
# that will then set a listener in that composition.
# l.setComposition(iface.activeComposers()[0].composition())
def unload(self):
"""Removes the plugin menu item and icon from QGIS GUI."""
for action in self.actions:
self.iface.removePluginMenu(
self.tr(u'&Atlas-based Profile Plotter'),
action)
self.iface.removeToolBarIcon(action)
# remove the toolbar
del self.toolbar
def run(self):
"""Run method that performs all the real work"""
# show the dialog
self.dlg.show()
# Run the dialog event loop
result = self.dlg.exec_()
# See if OK was pressed
if result:
# Do something useful here - delete the line containing pass and
# substitute with your code.
pass
class AtlasListener():
# http://gis.stackexchange.com/questions/31410/how-to-implement-signals-on-add-or-modify-feature
# @pyqtSlot(composerView)
def setupAtlasListener(self, composerView):
print 'a composer was added.'
iface.messageBar().pushMessage("Error","We added a composer",
level=QgsMessageBar.CRITICAL)
# @pyqtSlot(feature)
def featureChanged(self, feature):
iface.messageBar().pushMessage("Error","The Atlas was
changed", level=QgsMessageBar.CRITICAL)
def setCompositionListener(self, iface):
iface.composerAdded.connect(self.setupAtlasListener)
print 'we set up an atlas listener.'
def setComposition(self, composition):
composition.atlasComposition().featureChanged.connect(self.featureChanged)
On Sat, Dec 24, 2016 at 10:46 PM, Shawn Tse <shawntse at gmail.com> wrote:
> Hi, thanks so much for the help. Right now the AtlasListener is throwing up a
>
> NameError: name 'QObject' is not defined
>
> I looked up the API and when instantiating the AtlasListener, I can
> pass a QObject into the constructor. What QObject should I put in
> there?
>
> Thanks
>
> On Thu, Dec 15, 2016 at 7:35 PM, Nyall Dawson <nyall.dawson at gmail.com> wrote:
>> On 14 December 2016 at 13:42, Shawn Tse <shawntse at gmail.com> wrote:
>>> Thanks, that looks like exactly the kind of function that I'm looking
>>> for. I'm using QGIS 2.18.0, I'm wondering, is there any way to use
>>> this function without having to select a menu item in the the plugin?
>>>
>>> I'm not sure how to get started, because most of the existing plugins
>>> seem to be activated by a menu item or a toolbar button in the main
>>> editor instead of via the atlas interface.
>>>
>>> Thank you and I really appreciate the help!
>>
>> Hi Shawn,
>>
>> Have a read up on how signals and slots work in PyQt. Basically you
>> can listen out for the signal and get it to trigger a function in your
>> python class. Untested psuedocode below:
>>
>> class AtlasListener(QObject):
>> def featureChanged(self, feature):
>> print('new feature: {}'.format(feature.id())
>>
>> def setComposition(self, composition):
>> composition.atlasComposition().featureChanged.connect(self.featureChanged)
>>
>> l=AtlasListener()
>> l.setComposition(iface.activeComposers()[0].composition())
>>
>>
>> Nyall
>>
>>
>>>
>>> On Mon, Dec 12, 2016 at 11:02 PM, Nyall Dawson <nyall.dawson at gmail.com> wrote:
>>>>
>>>>
>>>> On 13 Dec 2016 4:44 PM, "Shawn Tse" <shawntse at gmail.com> wrote:
>>>>
>>>> Hi all,
>>>>
>>>> I'm interested in being able to make graphs that update depending on
>>>> what the active feature in the atlas is. I know some python and a
>>>> little bit of the QGIS API, but I'm curious - is there some sort of
>>>> listener function for the atlas that gets called whenever the Preview
>>>> Atlas/Prev Feature/Next Feature/First Feature/Last Feature buttons are
>>>> pressed?
>>>>
>>>>
>>>> Try QgsAtlasComposition::featureChanged. See
>>>> https://qgis.org/api/classQgsAtlasComposition.html#ab1a15fdb6d20ebb1254ebb6714254fac
>>>>
>>>> Nyall
>>>>
>>>>
>>>> What I eventually want to do is to manipulate the node items that were
>>>> created in a recent updated version of QGIS, and use them to make a
>>>> line graph, gridlines, etc.
>>>>
>>>> I'm hoping to draw the data directly from the shapefiles themselves or
>>>> from a .csv file.
>>>>
>>>> I originally tried to use an expression in a text box to do this, but
>>>> it seems that expressions are unable to use custom functions to
>>>> manipulate the composer. So I'm hoping that there's some sort of
>>>> Listener method.
>>>>
>>>> Thanks.
>>>> _______________________________________________
>>>> Qgis-developer mailing list
>>>> Qgis-developer at lists.osgeo.org
>>>> List info: http://lists.osgeo.org/mailman/listinfo/qgis-developer
>>>> Unsubscribe: http://lists.osgeo.org/mailman/listinfo/qgis-developer
>>>>
>>>>
>>> _______________________________________________
>>> Qgis-developer mailing list
>>> Qgis-developer at lists.osgeo.org
>>> List info: http://lists.osgeo.org/mailman/listinfo/qgis-developer
>>> Unsubscribe: http://lists.osgeo.org/mailman/listinfo/qgis-developer
More information about the Qgis-developer
mailing list