QGroundControl UI customization

Hi All,

I’m pretty new to the drone scene, so please forgive any newbie mistakes I might (actually, will definitely) make.

I wanted to customize the UI of QGroundControl. I do not have any real idea where to start. I read the developer pages on their website here. Unfortunately, I was not able to make heads nor tails of where I am to start for this task.

I’m looking to completely overhaul the UI to use faded text, movable buttons, etc…

I have started looking into Qt and I believe I can do most of it with QML, but I needed some guidance as to where I would start modifying the UI files. Do I have to recompile the entire code or is there a directory where I can just add the modified QML files?

If someone could throw some light on to this, that would be great.

1 Like

Ok, well that’s going to be pretty involved! Qml files are compiled into resources so you need to recompile each time you change them. If you look at MainWindowInner.qml that is the starting point for the ui. From there you should be able to pull the string and work your way to all of the other parts of the ui.

Hello,

I’m also learning QML and going deep into QGroundControl. In order to customize UI, Im using:

  • Qt Creator (as IDE)
  • GNU/Linux (as OS)
  • grep & find (helps a lot searching the code)

Resources for the code I use:

It is very important that you understand perfectly how C++ integrates with QML

Finnally, compile much faster with:

Thanks for the heads up @DonLakeFlyer and @chodjo.

I have just had the chance to get back to looking at this project. I got around to compiling it. Now I will start taking a look at modifying the UI.

@DonLakeFlyer, I was wondering from which file I would start modifying the UI… Thank you for the information.

Any idea on how I would change the map provider, and bring in the map that gives a 3D perspective?

Start here and follow where it goes.

First of all, I’m just trying to learn the code, so you should take my advice and guiding taken with a grain of salt.

You can set different maps in The APPLICATION SETTINGS > GENERAL tab, under MAP PROVIDER.

So we start in MainWindowInner.qml. In the app we should go to the Application Settings tab in the main toolbar. So checking the qml, we find there is defined a custom type MainToolBar with id toolBar and defined as the main UI. We so, check MainToolBar.qml and get a QGCToolBarButton custom type:

        QGCToolBarButton {
            id:                 settingsButton
            anchors.top:        parent.top
            anchors.bottom:     parent.bottom
            exclusiveGroup:     mainActionGroup
            source:             "/res/QGCLogoWhite"
            logo:               true
            onClicked:          toolBar.showSettingsView()
            visible:            !QGroundControl.corePlugin.options.combineSettingsAndSetup
        }

So back to MainWindowInner.qml and see that onShowSettingsView points to mainWindow.showSettingsView:

function showSettingsView() {
    rootLoader.sourceComponent = null
    if(currentPopUp) {
        currentPopUp.close()
    }
    //-- In settings view, the full height is available. Set to 0 so it is ignored.
    ScreenTools.availableHeight = 0
    hideAllViews()
    if (settingsViewLoader.source != _settingsViewSource) {
        settingsViewLoader.source  = _settingsViewSource
    }
    settingsViewLoader.visible  = true
    toolBar.checkSettingsButton()
}

_settingsViewSource is a property string that points to “AppSettings.qml”, so there we go. Here we have a rectangle that holds a QGCFlickable, where a Repeater (http://doc.qt.io/qt-5/qml-qtquick-repeater.html) instantiates a number of QGCButton type components using a model:

            model:  QGroundControl.corePlugin.settingsPages

So now, based on how C++ integrates with QML, we have to search, in this case, for a Q_PROPERTY called settingsPage. In my case, a grep search through the code takes me to QGCCorePlugin.h were we find:

Q_PROPERTY(QVariantList         settingsPages           READ settingsPages                                  NOTIFY settingsPagesChanged)

So, lets take a look at that code in QGCCorePlugin.cc:

QVariantList &QGCCorePlugin::settingsPages()
{
if(!_p->pGeneral) {
_p->pGeneral = new QmlComponentInfo(tr(“General”),
QUrl::fromUserInput(“qrc:/qml/GeneralSettings.qml”),
QUrl::fromUserInput(“qrc:/res/gear-white.svg”));
_p->settingsList.append(QVariant::fromValue((QmlComponentInfo*)_p->pGeneral));
_p->pCommLinks = new QmlComponentInfo(tr(“Comm Links”),
QUrl::fromUserInput(“qrc:/qml/LinkSettings.qml”),
QUrl::fromUserInput(“qrc:/res/waves.svg”));
_p->settingsList.append(QVariant::fromValue((QmlComponentInfo*)_p->pCommLinks));
_p->pOfflineMaps = new QmlComponentInfo(tr(“Offline Maps”),
QUrl::fromUserInput(“qrc:/qml/OfflineMap.qml”),
QUrl::fromUserInput(“qrc:/res/waves.svg”));
_p->settingsList.append(QVariant::fromValue((QmlComponentInfo*)_p->pOfflineMaps));
_p->pMAVLink = new QmlComponentInfo(tr(“MAVLink”),
QUrl::fromUserInput(“qrc:/qml/MavlinkSettings.qml”),
QUrl::fromUserInput(“qrc:/res/waves.svg”));
_p->settingsList.append(QVariant::fromValue((QmlComponentInfo*)_p->pMAVLink));
_p->pConsole = new QmlComponentInfo(tr(“Console”),
QUrl::fromUserInput(“qrc:/qml/QGroundControl/Controls/AppMessages.qml”));
_p->settingsList.append(QVariant::fromValue((QmlComponentInfo*)_p->pConsole));
#if defined(QT_DEBUG)
//-- These are always present on Debug builds
_p->pMockLink = new QmlComponentInfo(tr(“Mock Link”),
QUrl::fromUserInput(“qrc:/qml/MockLink.qml”));
_p->settingsList.append(QVariant::fromValue((QmlComponentInfo*)_p->pMockLink));
_p->pDebug = new QmlComponentInfo(tr(“Debug”),
QUrl::fromUserInput(“qrc:/qml/DebugWindow.qml”));
_p->settingsList.append(QVariant::fromValue((QmlComponentInfo*)_p->pDebug));
#endif

The code is pointing us to GeneralSettings.qml.

                    //-- Map Provider
                    Row {
                        spacing:    ScreenTools.defaultFontPixelWidth
                        visible:    _mapProvider.visible
                        QGCLabel {
                            text:       qsTr("Map Provider:")
                            width:      _labelWidth
                            anchors.verticalCenter: parent.verticalCenter
                        }
                        FactComboBox {
                            width:      _editFieldWidth
                            fact:       _mapProvider
                            indexModel: false
                            anchors.verticalCenter: parent.verticalCenter
                        }
                    }

We have a Fact defined:

property Fact _mapProvider:                 QGroundControl.settingsManager.flightMapSettings.mapProvider

So here is where map provider is defined. But we dont want to know who is the provider, but where its implemented the flight map. But now we know how the app calls to get the name of the map he wants to provide. So another grep search:

jguillen@HarryPotter:~/workspace/qgroundcontrol/src$ grep -r “QGroundControl.settingsManager.flightMapSettings.mapProvider” .
./ui/preferences/GeneralSettings.qml: property Fact _mapProvider: QGroundControl.settingsManager.flightMapSettings.mapProvider
./FlightMap/FlightMap.qml: target: QGroundControl.settingsManager.flightMapSettings.mapProvider
jguillen@HarryPotter:~/workspace/qgroundcontrol/src$

So we open FlightMap.qml and find that has a Map QML type (Map QML Type | Qt Location 5.15.16). You can follow from here.

Good luck :wink:

Hi! Thanks for sharing, this info is helping me a lot.
I’m trying to develop some improvements on QGC. Mainly add sliders (just like virtual joystick) on mainview to send PWM commands to FC channels.
I’m wondering about the best way to do this. Is it possible to edit these .qml files in design mode?

You can only edit .qml files in a text editor.

Isn’t it MainWindowHybrid.qml starting point for linux/windows/Mac and MainWindowNative.qml starting point for android

MainWindowInner.qml is the starting point for everything which then loads either MainWindowHybrid for desktop buids and MainWindowNative for mobile builds.

hi
I found that the MainWindowInner.qml is now replaced or renamed. It seems it is MainRootWindow.qml now. Is there a way to track the new file for any other same problems? I think git can help. any suggestion?
The question is what is the starting point now?

I’m not sure what you are asking. As you say the new main window qml file is MainRootWindow.qml. That is correct.

Hello, im a total noob in app development. Im trying to work on customizing the UI for QGC. Im able to open the project using Qt Creator and successfully build it. Im wondering if it is possible to use design view (Qt or Visual Studio) to customize the UI? Or is it only possible through qml files?

Sorry if the question sounds dumb but I really do appreciate your time. Thanks.

You cannot use the visual designers to modify the QGC ui.

Thank you for the reply Don. I managed to edit the layouts of the UI. But I have another question:

I want to add a button to the App Settings, so I duplicate the HelpSettings.qml and rename it to NewFeatureSettings.qml and change what’s necessary inside the file. I also add this button in QGCCorePlugin.cc which results in the button appearing in the App Settings column. However, when built, the console shows “qrc:/qml/NewFeatureSettings.qml: No such file or directory” even after I added the qml file into the CMakeList.txt which results in the button (when clicked,) not showing any text like in Help Settings.
How to add the qml properly into the project path? Thank you in advance.

1 Like

You need to add the Qml file to you custom resouce (.qrc) file

Hi,
If I understood well, there isn’t any option to edit .qml in form editor with QtCreator?
When I changed to form editor mode, there are some warnings in components at the navigator tab and shows blank background mainWindow…
Thanks in advance.

That will not work. You must use a text editor.

1 Like

It’s a shame because I’m newby using Qt with c++ and sure this option would be easier.
But, Thanks for your fast reply!

how do we trace which .cc file is linked with a particular qml file?
thanks in advance