Can't access user folder in qml



  • Hello,
    I am trying to load the content of a user folder in QML, but instead I always get the application's folder.

            ListView {
                id: listView1
                x: 0
                width: 288
                height: 256
                anchors.top: parent.top
                anchors.topMargin: 16
                anchors.horizontalCenter: parent.horizontalCenter
                delegate: listviewdelegate
                model: listviewmodel
                clip: true;
    
                FolderListModel {
                    id: listviewmodel
                    rootFolder: scenario.serializationPath
                    nameFilters: ["*.xml"]
                }
    
                Component{
                    id:listviewdelegate
                    Text {
                        text: fileName
                        color: m_colorDefault
                        font.pixelSize: m_iFontSizeMin
    
                        }
                    }
    
                }      
    

    The scenario.serializationaPath is a Q_PROPERTY declared in my cpp class:

    class Scenario : public QObject
    {
        Q_OBJECT
        Q_PROPERTY(QString serializationPath READ serializationPath WRITE setSerializationPath NOTIFY serializationPathChanged)
    
    private:
        QString m_sSerializationPath;
    public:
        explicit Scenario(QObject *parent = 0);
        ~Scenario();
    
        QString serializationPath() const;
        void setSerializationPath(QString s);
    
    signals:
        void serializationPathChanged();
    
    public slots:
    };
    

    And here is how I initialize it:

    Scenario::Scenario(QObject *parent) : QObject(parent)
    {
        QString sDir = QStandardPaths::locate(QStandardPaths::DocumentsLocation, QString(), QStandardPaths::LocateDirectory);
        if(!QString(sDir).isEmpty())
            setSerializationPath(sDir);
    }
    
    QString Scenario::serializationPath() const{
        return m_sSerializationPath;
    }
    
    void Scenario::setSerializationPath(QString s){
        if(m_sSerializationPath != s)
        {
            m_sSerializationPath = s;
            emit serializationPathChanged();
        }
    }
    

    If i use m_sSerializationPath in the C++ part of my app, it works fine and I write/read files from my user folder.
    But in the QML part, it doesn't work and instead I get the application's runtime folder.

    Thanks for your help!

    Regards


  • Moderators

    @bguivarch I guess what you are looking for is folder and not rootFolder?



  • Hello,
    I also tried with folder and I get the same result as with rootFolder : both properties target application's runtime folder instead of the value in scenario.serializationPath.

    Regards


  • Moderators

    @bguivarch Did you check what value is actually returned from C++ code ?



  • Hello,
    Yes I did some log output:
    -scenario.serializationPath is correct
    -footer is not correct

    Here is my QML code:

    FolderListModel {
                        id: listviewmodel
                        folder: scenario.serializationPath
                        nameFilters: ["*.xml"]
                        onFolderChanged: console.log("onFolderChanged folder set to "+folder);
                        Component.onCompleted: {
                            console.log("Component.onCompleted folder set to "+folder);
                            console.log("scenario.serializationPath is "+scenario.serializationPath);
                        }
                    }
    

    When I launch the app and get the Component.onCompleted output, folder targets the app's runtime folder.
    The onFooterChanged event is not triggered, as if the property wasn't reading the value of my C++ property.
    I checked in the C++ part that the property is updated and the signal launched for the QML (my Q_PROPERTY has a NOTIFY value in its declaration).

    As a reminder, here is how I set the prop in the C++:

    Scenario::Scenario(QObject *parent) : QObject(parent)
    {
        m_pCurrentItem = NULL;
        m_sScenarioFileName = "";
        m_pCurrentPath = NULL;
        m_sScenarioName = "";
        m_sSerializationPath = "";
        QString sDir = QStandardPaths::locate(QStandardPaths::DocumentsLocation, QString(), QStandardPaths::LocateDirectory);
        if(!QString(sDir).isEmpty())
            setSerializationPath(sDir);
    }
    
    void Scenario::setSerializationPath(QString s){
        if(m_sSerializationPath != s)
        {
            m_sSerializationPath = s;
            qDebug() << "changing m_sSerializationPath to " << m_sSerializationPath;
            emit serializationPathChanged();
        }
    }
    

    And the output I got:

    Starting F:\QtDev\build-ScenarioEditor-Desktop_Qt_5_5_0_MSVC2012_32bit-Debug\debug\ScenarioEditor.exe...
    QML debugging is enabled. Only use this in a safe environment.
    changing m_sSerializationPath to  "C:/Users/BG/Documents/"
    qml: Component.onCompleted folder set to file:///F:/QtDev/build-ScenarioEditor-Desktop_Qt_5_5_0_MSVC2012_32bit-Debug
    qml: scenario.serializationPath is C:/Users/BG/Documents/
    

    Regards


  • Moderators

    @bguivarch
    onFolderChanged is proabably not triggered because by the time you emit the signal from the constructor the QML component is not initialized. Try setSerializationPath after some time.



  • Hello,
    So I tried to set the folder property when the component is completed.
    The log output value is correct, but the files displayed are still those of the application's runtime folder.

    Here is a snippet for the FolderListModel:

    FolderListModel {
                        id: listviewmodel
                        folder: scenario.serializationPath
                        nameFilters: ["*.xml"]
                        onFolderChanged: console.log("onFolderChanged folder set to "+folder);
                        Component.onCompleted: {
                            folder = scenario.serializationPath;
                            console.log("Component.onCompleted folder set to "+folder);
                            console.log("scenario.serializationPath is "+scenario.serializationPath);
    
                        }
                    }
    

    And the output:

    Starting F:\QtDev\build-ScenarioEditor-Desktop_Qt_5_5_0_MSVC2012_32bit-Debug\debug\ScenarioEditor.exe...
    QML debugging is enabled. Only use this in a safe environment.
    changing m_sSerializationPath to  "C:/Users/BG/Documents/"
    qml: Component.onCompleted folder set to c:/Users/BG/Documents/
    qml: scenario.serializationPath is C:/Users/BG/Documents/
    

    I thought that maybe the ending "/" was causing troubles, so I tried this:

    folder = scenario.serializationPath+"Documentations";
    

    Which led to this correct output:

    Starting F:\QtDev\build-ScenarioEditor-Desktop_Qt_5_5_0_MSVC2012_32bit-Debug\debug\ScenarioEditor.exe...
    QML debugging is enabled. Only use this in a safe environment.
    changing m_sSerializationPath to  "C:/Users/BG/Documents/"
    qml: Component.onCompleted folder set to c:/Users/BG/Documents/Documentations
    qml: scenario.serializationPath is C:/Users/BG/Documents/
    

    Yet, it didn't display the files of the folder I am asking for.
    I really don't understand what is going on here...

    Regards


  • Moderators

    What if you dont call setSerializationPath in the constructor and call it from somewhere else ? Does in that case onFolderChanged signal handler triggered ?



  • Hello,
    I tried to set it in the main but it didn't change anything. Maybe it is too early in the process.
    I'll try using a timer in QML to update the folder property later on.



  • Hello,

    So I added a timer in the QML and in this timer, set the folder property.
    I started it when the FolderListModel is completed, but it didn't work.
    Then I tried when the whole QML component that holds the FolderListModel is display (it is hidden by default) by a user action, but still got a fail.

    For a final test, I used a FileDialog just to check if with another QML component, I could be able to target my User folder, and this time it worked well. Problem is, after looking into FileDialog doc, I can't find a way to limit the user to only the folder I have set.

    Regards


  • Moderators

    That's odd. Can you post a complete working example which can reproduce your problem ?



  • Hello,
    Sorry for the late answer.
    Here is the full code:

    /*!
    
      \class LoadScenarioDialog
      \author BG (bg@faros.com)
      \brief This QML component defines a dialog for loading a scenario.
      It is based upon a GenericDialog component with UI for loading a file.
      \date 2016/09/08 Creation
      !*/
    import QtQuick 2.0
    import Qt.labs.folderlistmodel 2.1
    
    Item {
        anchors.fill: parent
    
        property string m_sFileForLoading
    
        GenericDialog{
            id:genericdialog1
            anchors.fill: parent
    
            Rectangle {
                id: background
                width:320
                height:368
                color: "blue"
                anchors.horizontalCenter: parent.horizontalCenter
                anchors.verticalCenter: parent.verticalCenter
    
                ListView {
                    id: listView1
                    x: 0
                    width: 288
                    height: 256
                    anchors.top: parent.top
                    anchors.topMargin: 16
                    anchors.horizontalCenter: parent.horizontalCenter
                    delegate: listviewdelegate
                    model: listviewmodel
                    clip: true;
    
                    //test 1 : shows all in application's folder
    //                FolderListModel{
    //                    id:listviewmodel
    //                }
    
                    //test 2 : shows only XML files in application's folder
    //                FolderListModel{
    //                    id:listviewmodel
    //                    nameFilters: ["*.xml"]
    //                    showDirs: false
    //                }
                    //test 3 : displays all qml file of the required folder
    //                FolderListModel {
    //                    id: listviewmodel
    //                    rootFolder: "F:/QtDev/Sources.ScenarioEditor"
    //                    folder:"/qml"
    //                    nameFilters: ["*.qml"]
    //                }
                    //test 4 : we can't target a folder which is not in the same partition has the application
                    FolderListModel {
                        id: listviewmodel
                        folder:"C:/Users/BG/Documents"
                        nameFilters: ["*.xml"]
                    }
    
                    Component{
                        id:listviewdelegate
                        Text {
                            text: fileName
                            color: m_colorDefault
                            font.pixelSize: m_iFontSizeMin
    
                            MouseArea{
                                id:mouseareadelegate
                                anchors.fill: parent
                                onClicked:{
                                    console.log("count is "+listviewmodel.get(0,"count"));
                                    console.log("folder is "+listviewmodel.get(0,"folder"));
                                    console.log("filename is "+listviewmodel.get(0,"filename"));
    
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    
    
    

    And here is the GenericDialog.qml component

    /*!
    
      \class GenericDialog
      \author BG (bg@faros.com)
      \brief This QML component defines a full window mask for mouse events.
      It is intended to be used for dialog-like components creation. As so, it is used by SaveScenarioDialog and LoadScenarioDialog.
      \date 2016/09/06 Creation
      !*/
    import QtQuick 2.0
    
    Item {
        id:root
        anchors.fill: parent
    
        Rectangle{
            id:mask
            color:"#bf000000"
            anchors.fill: parent
    
            MouseArea{
                anchors.fill: parent
            }
        }
    }
    

    I had to modify a bit my code to skip properties defined elsewhere or C++ object, but I think you will be able to reproduce my issue with those two files.

    Regards,


  • Moderators

    @bguivarch Works perfectly using Qt 5.5 on Ubuntu. Instead of C:/Users/BG/Documents did you try another path? May be this directory doesn't have access ?



  • Are you stuck at using < 5.1 ? in other words can you just use
    FileDialog ? and not the Qt.labs.folderlistmodel 2.1 ?

    StanderedPaths is already in it

    FileDialog{
        folder: shortcuts.documents
    }
    
    

    I made a video about this located Here on Youtube



  • Hello,

    @p3c0 I finally made it work, but now I am facing troubles on the filtering of files.
    Here is a snippet:

    FolderListModel {
                        id: listviewmodel
                        showDirs: false
                        //works fine and filters XML
    //                    folder:"file:/F:/QtDev/Sources.ScenarioEditor"
    //                    nameFilters: ["*.xml"]
                        //targets C:\Users\BG/Documents and works fine too but doesn't filter XML
                        folder:"file:/"+scenario.serializationPath
                        nameFilters: ["*.xml"]
                    }
    

    I'll go on investigating...

    @JosephMills I am currently using Qt 5.5.0. I looked at FileDialog but I am not quite satisfy with this solution as I am trying to give a specific look & feel to the windows of my application.

    Regards


Log in to reply
 

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