QStandardPaths not available in QML?



  • I've been using the FileDialog component and got used to the shortcut property. Then when I went to access the QStandardPaths elsewhere, in a routine handing fileIO, I realized that this isn't exposed to QML.

    Is there some relatively easy way to make this available (short of writing a plugin like the Wrapper for Qt file access in QML which I don't know how to use)?

    thanks!


  • Lifetime Qt Champion

    Hi,

    You can create a small QObject derived class that will return the values you're interested in using Q_INVOKABLE functions.



  • You don't have to write a plugin. As SGaist said, just write a simple QObject-derived class. It can be a single .h file and a call to qmlRegisterType in main.cpp.



  • @xargs1

    Hey I did it! (and it didn't hurt too much...)

    Am I doing it right ;-) And am I correct in thinking that I can't generalize this (e.g. have a "getPath(int pathType)? I tried passing in an int as an index to the enum: enum QStandardPaths::StandardLocation but that threw a type error.

    #ifndef UTILITYRP
    #define UTILITYRP
    
    #include <QObject>
    #include <QStandardPaths>
    
    class UtilityRP : public QObject
    {
        Q_OBJECT
    
    public:
         Q_INVOKABLE QStringList getDesktopLocation() {
    
            return QStandardPaths::standardLocations(QStandardPaths::DesktopLocation);
        }
    };
    
    #endif // UTILITYRP
    
    
    

  • Lifetime Qt Champion

    You can create a Q_ENUM and use it as parameter to your function. You can make it match the values you need from QStandardPaths so there's no translation needed just a cast.



  • @SGaist

    thanks! got that to work (assuming I am doing the cast correctly with static_cast<QStandardPaths::StandardLocation>(location);).

    #ifndef UTILITYRP
    #define UTILITYRP
    
    #include <QObject>
    #include <QStandardPaths>
    
    class UtilityRP : public QObject
    {
        Q_OBJECT
    
    public:
        Q_INVOKABLE QStringList getPath(int location) {
            QStandardPaths::StandardLocation loc = static_cast<QStandardPaths::StandardLocation>(location);
            return QStandardPaths::standardLocations(loc);
        }
    };
    
    #endif // UTILITYRP
    

  • Lifetime Qt Champion

    In this case, using an int is not clean. Your QML code won't make any sense (i.e. what is location 1 ?). You should really take the time to implement an enum for that. So that if any off the enum value changes, you won't have to update that part of your code and it will make it easier to read.



  • @SGaist

    Thanks. Yes, I realize using an arbitrary int kind of defeats the purpose of using an enum but I couldn't figure out how to do it on the QML side – the docs ( enumeration QML Basic Type ) are not very clear, nor how to expose the QStandardPaths:: StandardLocation to the QML.


  • Lifetime Qt Champion

    That's the QML doc, you should do it from C++. Add an enum to your class that maps the StandardLocation values to your own and declare it as a Q_ENUM.



  • @SGaist

    Sorry, not following. Can you point me to an example that does that?


  • Lifetime Qt Champion

    #include <QApplication>
    #include <QQmlApplicationEngine>
    #include <QQmlContext>
    #include <QStandardPaths>
    #include <QQmlComponent>
    
    class UtilityRPAttachedEnums : public QObject
    {
        Q_OBJECT
    public:
        enum StandardLocation {
            DesktopLocation       = QStandardPaths::DesktopLocation,
            DocumentsLocation     = QStandardPaths::DocumentsLocation,
            FontsLocation         = QStandardPaths::FontsLocation,
            ApplicationsLocation  = QStandardPaths::ApplicationsLocation,
            MusicLocation         = QStandardPaths::MusicLocation,
            MoviesLocation        = QStandardPaths::MoviesLocation,
            PicturesLocation      = QStandardPaths::PicturesLocation,
            TempLocation          = QStandardPaths::TempLocation,
            HomeLocation          = QStandardPaths::HomeLocation,
            DataLocation          = QStandardPaths::DataLocation,
            CacheLocation         = QStandardPaths::CacheLocation,
            GenericCacheLocation  = QStandardPaths::GenericCacheLocation,
            GenericDataLocation   = QStandardPaths::GenericDataLocation,
            RuntimeLocation       = QStandardPaths::RuntimeLocation,
            ConfigLocation        = QStandardPaths::ConfigLocation,
            GenericConfigLocation = QStandardPaths::GenericConfigLocation,
            DownloadLocation      = QStandardPaths::DownloadLocation,
        };
        Q_ENUMS(StandardLocation)
    
    public:
        UtilityRPAttachedEnums(QObject *parent)
            : QObject(parent)
        {}
        Q_INVOKABLE QStringList getPath(StandardLocation location) {
            QStandardPaths::StandardLocation loc = static_cast<QStandardPaths::StandardLocation>(location);
            return QStandardPaths::standardLocations(loc);
        }
    };
    
    class UtilityRP : public QObject
    {
        Q_OBJECT
    public:
        static UtilityRPAttachedEnums *qmlAttachedProperties(QObject *object)
        {
            return new UtilityRPAttachedEnums(object);
        }
    };
    
    QML_DECLARE_TYPEINFO(UtilityRP, QML_HAS_ATTACHED_PROPERTIES)
    
    int main(int argc, char *argv[])
    {
        QApplication app(argc, argv);
        qmlRegisterUncreatableType<UtilityRP>("org.test.qmlcomponents", 1, 0, "UtilityRP", "Static");
    
        QQmlApplicationEngine engine;
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    
        return app.exec();
    }
    
    #include "main.moc"
    

    main.qml

    import QtQuick 2.3
    import QtQuick.Controls 1.2
    
    import org.test.qmlcomponents 1.0
    
    ApplicationWindow {
        visible: true
        width: 640
        height: 480
        title: qsTr("Hello World")
    
        menuBar: MenuBar {
            Menu {
                title: qsTr("File")
                MenuItem {
                    text: qsTr("&Open")
                    onTriggered: console.log("Open action triggered");
                }
                MenuItem {
                    text: qsTr("Exit")
                    onTriggered: Qt.quit();
                }
            }
        }
    
        MouseArea {
            id: mouseArea
            anchors.fill: parent
            Label {
                id: label
                text: qsTr("Click me")
                anchors.centerIn: parent
            }
    
            onClicked: {
                label.text = UtilityRP.getPath(UtilityRP.DesktopLocation);
            }
        }
    }
    


  • @SGaist

    hey thanks! I'll be chewing on that for a while


  • Qt Champions 2016

    @SGaist You should start a library project in Github. :D


  • Lifetime Qt Champion

    @benlau Do you mean a "nice to have helper functions/classes" library ? :)


  • Qt Champions 2016


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.