1

I need advice on how to specify the paths to my QML and resources (icon) in my simple QtQuick QML Python application on KDE. The only related question I found here was: Deploy a Qt project on linux

My question is different. My only target for deploying my application is KDE; therefore, I do not need to bundle Qt libraries and my application has no other dependencies. I only need to deploy my python and QML files and an application icon (png).

One other wrinkle is that, in the future, I want to be able to provide certain updates via QML files only. I plan to push out, when needed, a single new QML file without having to deploy a new version of the application.

This leads me to believe that I should not use Qt resource system. However, lacking any experience with that system or with deploying applications in general, I seek advice.

I do not want to hard code the path to my icon and main QML file in my main.py file upon deploying. Furthermore, the following code does not give me the location of any of my application's files:

QCoreApplication.applicationDirPath()

It returns /usr/bin (the location of python) which is not a location suitable for my QML file or application icon.

How can I locate my QML and resource files within the executing __main__ method?

Here is my main.py:

import sys
from PyQt5.QtWidgets import QApplication
from PyQt5.QtCore import QUrl
from PyQt5.QtQml import QQmlApplicationEngine
from PyQt5.QtGui import QIcon


if __name__ == '__main__':
    app = QApplication(sys.argv)

    engine = QQmlApplicationEngine()
    engine.load(QUrl.fromLocalFile('view.qml'))
    app.setWindowIcon(QIcon('appicon.png'))

    if not engine.rootObjects():
        sys.exit(-1)
    sys.exit(app.exec_())

Here is my view.qml

import QtQuick.Window 2.2
import QtQuick 2.2
import QtQuick.Controls 2.14

Window {
    id: root
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")
    }

This code works when I execute python main.py from the local directory. However, if I deploy my python, qml and icon files to, say, /usr/local/bin I have to hard-code that path into the python file as follows.

    engine.load(QUrl.fromLocalFile('/usr/local/bin/view.qml'))
    app.setWindowIcon(QIcon('/usr/local/bin/appicon.png'))

I do not want to do this. I am looking for other alternatives that do not involve hard-coding the path.

This question is not about distribution-specific packaging. Assume I will use something like the "generic" method discussed here -- such as a shell script (and assume the installing user will have sudo rights).

MountainX
  • 6,217
  • 8
  • 52
  • 83
  • Qt Creator helps bundle resource files, which is why I mentioned it. My problem is related to finding the path to my QML and icon files at runtime. – MountainX Jan 19 '20 at 06:57
  • My question is not about Qt Creator. In the question I mentioned that I was agnostic toward using it. I will edit the question and remove any reference to Qt Creator because it seems to be diverting attention from my actual question. – MountainX Jan 19 '20 at 08:17
  • I think I understand better now. You want to get the QML path without hard code (without specifying the full path). Where is the QML related to .py? You also indicate that your project has at least 3 components: .py, .qml and an icon, you could provide a simple and minimalist example of your project so that you can better appreciate your problem. – eyllanesc Jan 19 '20 at 08:25
  • @eyllanesc Thank you. I can put the python, qml and icon files all in the same directory. I will edit the question to provide an example. – MountainX Jan 19 '20 at 08:35
  • @eyllanesc the question has been updated. – MountainX Jan 19 '20 at 08:49

1 Answers1

2

The idea in this case is to create absolute paths using relative paths with respect to a main element. For example in this case you could use the main.py directory path (which can be obtained by the solutions provided to this answer: How do I get the path and name of the file that is currently executing?) to obtain the other paths.

import os
import sys

from PyQt5.QtCore import QUrl
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication
from PyQt5.QtQml import QQmlApplicationEngine


CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))


if __name__ == "__main__":
    app = QApplication(sys.argv)

    engine = QQmlApplicationEngine()
    engine.load(QUrl.fromLocalFile(os.path.join(CURRENT_DIR, "view.qml")))
    app.setWindowIcon(QIcon(os.path.join(CURRENT_DIR, "appicon.png")))

    if not engine.rootObjects():
        sys.exit(-1)
    sys.exit(app.exec_())
├── appicon.png
├── main.py
└── view.qml
eyllanesc
  • 235,170
  • 19
  • 170
  • 241