Unsolved 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
-
@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
-
@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 correctHere 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
-
@bguivarch
onFolderChanged
is proabably not triggered because by the time you emit the signal from the constructor the QML component is not initialized. TrysetSerializationPath
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
-
What if you dont call
setSerializationPath
in the constructor and call it from somewhere else ? Does in that caseonFolderChanged
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
-
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,
-
@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