This problem is caused by uic
not working properly. I am not sure exactly why but I can show the symptoms and a workaround.
The initial plugin .ui
file has an empty resources
element:
<resources/>
When you edit the resources for the plugin in QtDesigner this changes to:
<resources>
<include location="resources.qrc"/>
</resources>
This is the source of the problem. If you change the .qrc file in that include tag to resourcesXXX.qrc
the error will change to No module named resourcesXXX_rc
.
Note: the following is based upon a plugin build with 'test' entered into all fields of the QGIS plugin builder.
In the test_dialog.py file the following lines compile the .ui file:
FORM_CLASS, _ = uic.loadUiType(os.path.join(
os.path.dirname(__file__), 'test_dialog_base.ui'))
This is where the error is occurring.
Edit your .ui
file to change back to <resources/>
and the problem is resolved. Until you edit your dialog in QtDesigner again. You must make this edit to the .ui
file after each time you edit your dialog.
The solution to this is to change your plugin to work like earlier versions of the plugin worked. This involves replacing the uic call and the class lines in the _dialog.py file. Replace these lines:
FORM_CLASS, _ = uic.loadUiType(os.path.join(
os.path.dirname(__file__), 'test_dialog_base.ui'))
class testDialog(QtGui.QDialog, FORM_CLASS):
with:
from test_dialog_base import Ui_testDialogBase
class testDialog(QDockWidget, Ui_testDialogBase):
You will now have to run
pyuic4 -x test_dialog_base.ui > test_dialog_base.py
when you first create your plugin and each time you edit your plugin dialog with QtDesigner. This was the old plugin method.
Whether to edit the .ui
file or the run pyuic4
each time is your choice.
In order to use the result in an expression, a custom python expression is necessary. Here's the code I've come up with:
from qgis.core import *
from qgis.gui import *
from qgis.utils import iface
@qgsfunction(args='auto', group='Custom')
def getScale(composerName, mapName, feature, parent):
# dictionary to store QgsComposerView.composition() items by name
compDict = {}
for comp in iface.activeComposers():
# workaround to get name: read it from window title
compDict[comp.composerWindow().windowTitle()] = comp.composition()
mapScale = 0 # default to be returned if scale not found
if composerName in compDict:
mapItem = compDict[composerName].getComposerItemById(mapName)
if mapItem:
mapScale = mapItem.scale()
return mapScale
The first challenge is getting a composer by name. Create a dictionary to hold the composers, then iterate over the activeComposers() list, storing them by name in the dictionary.
Next, if the composer name we're looking for is in the list, get the requested map and it's extent. Return either it or 0 to denote not found.
This works great with an atlas controlled map:
In this case the expression used for the label is:
'scale' || getScale('Composer 1', 'Map 0')
Best Answer
In my GNU/Linux Debian, at the Python Console of QGIS, I type:
and I got:
You can also assign print command to a variable for using it programmatically after some string manipulations and by using regular expressions python module (re). For example:
that produces:
In this case, it was individualized the 'Package Data Path'.
Editing Note:
I found out that it could be easier with these commands:
where it's produced: