Yes that was also my first guess. I have just created a workaround using a small C++ helper class.
Here is a little context for the issue:
- The path returned from the firebase upload function is of type string
- The “source” property of the image is of type url, so internally a QUrl
- When passing this string to the “source” property, it is converted to a url automatically, using the appropriate constructor, which ALWAYS will perform url encoding, so the %2F is effectively decoded to a /, which breaks the url
So the proposed workaround here is:
QUrl has a method to create a url from a string that is already encoded (which is the case for us), namely: https://doc.qt.io/qt-5/qurl.html#fromEncoded
- Take the string type url and pass it to a helper class
- This helper class creates a url from the string using the fromEncoded method and returns it
- Use the return url in your QML code, e.g. set it as image source
Here are the relevant code parts:
firebaseurlhelper.h
#ifndef FIREBASEURLHELPER_H
#define FIREBASEURLHELPER_H
#include <QObject>
#include <QUrl>
class FirebaseUrlHelper : public QObject
{
Q_OBJECT
public:
explicit FirebaseUrlHelper(QObject *parent = nullptr);
signals:
public slots:
QUrl fromDownloadUrl(const QString &path);
};
#endif // FIREBASEURLHELPER_H
firebaseurlhelper.cpp
#include "firebaseurlhelper.h"
FirebaseUrlHelper::FirebaseUrlHelper(QObject *parent) : QObject(parent)
{
}
QUrl FirebaseUrlHelper::fromDownloadUrl(const QString &path)
{
return QUrl::fromEncoded(path.toUtf8());
}
main.cpp
#include <QApplication>
#include <FelgoApplication>
#include <QQmlApplicationEngine>
#include "firebaseurlhelper.h"
// uncomment this line to add the Live Client Module and use live reloading with your custom C++ code
//#include <FelgoLiveClient>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
FelgoApplication felgo;
// Use platform-specific fonts instead of Felgo's default font
felgo.setPreservePlatformFonts(true);
// Make this new type available in QML.
// You could also use a context property instead, more info here: https://felgo.com/cross-platform-development/how-to-expose-a-qt-cpp-class-with-signals-and-slots-to-qml
qmlRegisterType<FirebaseUrlHelper>("com.felgo.firebaseurlhelper", 1, 0, "FireBaseUrlHelper");
QQmlApplicationEngine engine;
felgo.initialize(&engine);
// Set an optional license key from project file
// This does not work if using Felgo Live, only for Felgo Cloud Builds and local builds
felgo.setLicenseKey(PRODUCT_LICENSE_KEY);
// use this during development
// for PUBLISHING, use the entry point below
felgo.setMainQmlFileName(QStringLiteral("qml/Main.qml"));
// use this instead of the above call to avoid deployment of the qml files and compile them into the binary with qt's resource system qrc
// this is the preferred deployment option for publishing games to the app stores, because then your qml files and js files are protected
// to avoid deployment of your qml files and images, also comment the DEPLOYMENTFOLDERS command in the .pro file
// also see the .pro file for more details
// felgo.setMainQmlFileName(QStringLiteral("qrc:/qml/Main.qml"));
engine.load(QUrl(felgo.mainQmlFileName()));
// to start your project as Live Client, comment (remove) the lines "felgo.setMainQmlFileName ..." & "engine.load ...",
// and uncomment the line below
//FelgoLiveClient client (&engine);
return app.exec();
}
Main.qml
import Felgo 3.0
import QtQuick 2.0
import com.felgo.firebaseurlhelper 1.0
App {
NavigationStack {
Page {
title: qsTr("Main Page")
Image {
source: firebaseUrlHelper.fromDownloadUrl("https://firebasestorage.googleapis.com/v0/b/project.appspot.com/o/users%2Fklegsz6x41Ob5BVn6wWzQfdhhk73%2Fbills%2Fdummy.pdf?alt=media&token=20a2e8d9-e84b-4208-a975-d30b9a77ec37")
anchors.centerIn: parent
onSourceChanged: console.debug("source changed" + source)
}
FireBaseUrlHelper {
id: firebaseUrlHelper
}
}
}
}
Note: To use QML live code reloading together with custom C++, refer to: https://felgo.com/updates/release-2-16-1-live-code-reloading-with-custom-c-and-native-code-for-qt
I hope this helps you solve the issue.
Cheers,
Alex