demo1_hello.qml

This is the main QML file that loads and unloads the plugin code and its toolbar buttons.

// <!--Imports...-->

import org.qfield 
import Theme  



Item {  
  id: plugin
  parent: iface.mapCanvas() 
  anchors.fill: parent 
  Loader {
    id: pluginLoader
    active: false
    anchors.fill: parent
    source: Qt.resolvedUrl('./components/d1_plugin_component.qml')
  }  
  QfToolButton {
    id: pluginButton
    bgcolor: Theme.darkGray
    iconSource: Theme.getThemeVectorIcon('ic_camera_photo_black_24dp')
    iconColor: Theme.mainColor
    round: true

    onClicked: {
      iface.logMessage("Loading d1_plugin_component.qml")
      pluginLoader.active = !(pluginLoader.active)
    }
  }

  Component.onCompleted: {
    iface.addItemToPluginsToolbar(
      pluginButton
    )
  }
}

Classes in Our Demo


QObject
|___ QtObject
|    |___  Item (Base for Visual Types, like QtWidget)
|    |    |___ Rectangle
|    |    |___ Text
|    |    |___ Image
|    |    |___ MouseArea
|    |    |___ Loader 
|    |    |___ Controls
|    |    |    |___ Button
|    |    |    |___ AbstractButton
|    |    |    |    |___ QToolButton
|    |    |    |    |    |___ QfToolButton
|    |___  Component (Container/Utility Class. Not related to Item!)
|    |___  Connections
|    |___  Other non visual types and utilities

Item (plugin):

Properties

Members of the Plugin Item:

Component.onCompleted

This is the signal-slot construction that triggers the addition of the pluginButton to the QField toolbar when the plugin item has been created.

Looking at Component.onCompleted within Item and also considering that the Loader loads a Component, one might be tempted to think that Component is the parent class of Item, and this signal is inherited.

This is not the case. Component and Item have nothing to do with each other.

Loader (pluginLoader):

A Loader is an Item that dynamically loads and unloads other Items. Loaders construct and destruct their Components when their "active" property value is toggled, which allows runtime triggers for construction and destruction. This makes it possible to trigger the loading of the plugin with a button.

Why We Need a Loader Here:

Our plugin will do things like reading layers in the project. We don't want this to happen until the project is loaded. In fact, we want our plugin code to wait until the user asks for it by clicking on the plugin's tool button or later selecting an object on the map.

If we put our plugin code directly into our root item without the Loader, we would be trying to read layers that don't exist yet and perform a lot of processing that may not be needed.

Properties

QfToolButton (pluginButton)

This is simple. QfToolButton is a tool button widget that we have connected to the Loader. We could use QToolButton, but we use QField's QfToolButton here so it maintains QField's design. For the rest of the plugin, I tend to prefer the Qt objects.

I can use QfToolButton or any other QField widget because I imported them from org.qfield.

This Item is not in the Loader because it is the Item that controls the Loader.

Properties

Remember, it's not Component.onClicked. Everything except onCompletion and onDestruction are members of the Item component and have nothing to do with Component.