Environment for Plugin Development

I’ve been attempting to create a plugin with the help of google’s gemini using the QField 4.0.6 AppImage but have run into some issues:

  • Issues with standard methods for accessing project and layers
  • Means of creating a feature without a GPS device present
  • Camera

I was hoping to make more progress in desktop before I start testing via zips to my phone. I was wondering how other people are working on plugins.

  • Building from source / using Windows / Mac?
  • Faking location
  • Can a web cam act as a camera for QField?
  • AppImage and running a less sandboxed environment?

Any hints or tips on setup would be much appreciated. I’ll paste below the summary of the struggles. Take with a pinch of salt - it’s an AI summary.

Summary of QML Plugin Issues: QField Linux AppImage

The Core Issue: Environment Sandboxing

The primary challenge is that the QML/JavaScript engine within the Linux AppImage appears to be strictly sandboxed or “decoupled” from the internal QGIS/QField object tree. While the UI loads correctly, the API bridges are either missing or returning null.

1. Restricted Access to the Project Object

Standard methods for accessing the project and its layers fail consistently:

  • iface.activeProject and iface.project return null or are reported as “Hidden.”

  • iface.mainWindow().activeLayer (as a property) and activeLayer() (as a function) both fail to return the currently highlighted layer in the sidebar.

  • Recursive searches through iface.mapCanvas().layers() or layerStack return undefined, suggesting the MapCanvas object is not exposing its layer registry to the QML context.

2. Inaccessible Hardware/UI Functions

The AppImage environment seems to block “Cross-Talk” between the plugin and the system hardware:

  • iface.nativeCamera() and iface.takePhoto(): Both return TypeError: not a function, indicating the camera bridge isn’t initialized or exposed to the plugin.

  • iface.digitizeFeature(): This core function (which should trigger the standard “Add Feature” UI) is inaccessible, leading to a “Hardware Lock” error.

3. Property vs. Function Discrepancies

There is an inconsistency in how the API is mapped in the AppImage build:

  • For example, mapCanvas().center is treated as a Property (variable) rather than a Function center(). This suggests the QML wrapper in the AppImage might be using an older or non-standard mapping compared to the Android/Windows versions.

I think i’ll inspect other plugins more closely on things like identifying active layer and such but I was wondering how location is tested on desktop. For instance running GitHub - opengisch/qfield-snap: Allow for snapping of photos to create a feature at the current device location. · GitHub hits an issue with no locatoin available when creating a feature on desktop.

Hi!

For the Snap-Plugin, the position check is on line 64 (currently) in main.qml:

      if (!positionSource.active || !positionSource.positionInformation.latitudeValid || !positionSource.positionInformation.longitudeValid) {
        mainWindow.displayToast(qsTr('Snap requires positioning to be active and returning a valid position'))
        return
      }

For positioning on Windows, I usually just use my web/provider location (don’t know how to better describe it), since for testing, ~100+m accuracy doesn’t really matter.

I believe there is currently an Issue with using the camera on Windows.

When starting to write a new Plugin on Windows, I usually copy the QField Template Plugin into a new subfolder in my plugins directory and open that in VSCode. Make sure to immediately push all your progress into a new github repostitory tho, since “uninstalling” your Plugin will forever delete your local project files with this approach :sweat_smile:

A great starting point for me was this webinar: https://www.youtube.com/watch?v=_X3cht6AYBk

The official QField API Documentation can be found here: https://api.qfield.org

The LLM is trying to access all the modules and functions as if you were editing the application code directly, which won’t work in a plugin context (it’s not very good at “understanding” that).

If you have trouble finding something or are not sure if/how something works, you can also always ask here in the community! :slightly_smiling_face: