QtQuickControls FileDialog Automation - qt

I'm trying to automate picking a file in QML in a QtQuick Controls FileDialog. How can I invoke FileDialog's accept with a specific fileUrl when the fileUrl property is read only?
The current attempt involves calling filedialog.clearSelection, filedialog.addSelection and finally filedialog.accept. clearSelection and addSelection are not documented but can be found in https://github.com/qt/qtquickcontrols/blob/dev/src/dialogs/qquickfiledialog.cpp (Assuming Qt has used a DefaultFileDialog as this can be system dependent)
However clearSelection seems to only work sporadically, having no affect if the same FileDialog has been used manually, hence the addSelection fails to set fileUrl.
The following is a QML file (loaded as a basic project within QtCreator) demonstrates this. with a manual file dialog open button and an automatic one:
import QtQuick 2.9
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.4
import QtQuick.Dialogs 1.3
Window {
visible: true;width: 200;height:200
FileDialog {id: filedialog; onAccepted: console.log("File Dialog Accepted: ", fileUrl, fileUrls);}
Row {
Button {text: "manual"; onClicked: filedialog.open()}
Button {
text: "auto_qml"
onClicked: {
console.log("Current selection:", filedialog.fileUrl, filedialog.fileUrls)
filedialog.clearSelection();
console.log("cleared selection:", filedialog.fileUrl, filedialog.fileUrls) // only clears selection if manual not used
let t = filedialog.addSelection("file:/home/user/tempfile.txt");
console.log("add selection success:", t) // a non existent file returns false, so file must exist
filedialog.accept()
}
}
}
}

As variant you can use Qt.labs.platform 1.1 library. It contains FileDialog with a little bit another behavior - file property is not read-only.
And you can do like so:
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.4
import Qt.labs.platform 1.1
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
FileDialog {id: filedialog; onAccepted: console.log("File Dialog Accepted: ", file, files);}
Row {
Button {text: "manual"; onClicked: filedialog.open()}
Button {
text: "auto_qml"
onClicked: {
filedialog.file = "file:/home/user/tempfile.txt";
console.log("Current selection:", filedialog.file, filedialog.files)
filedialog.accepted()
}
}
}
}

Related

Catch QML Component status/progress change signals

I'm trying to debug my QML application which is experiencing freezes at load. I'm not getting Component.onCompleted signals from any of my components, so I'm trying to check the Component.status changes, however QML is throwing a Cannot assign to non-existent property "onStatusChanged" warning when I try with the following example. How can I get notified of status or progress changes on components?
import QtQuick 2.14
import QtQuick.Window 2.14
import QtQuick.Controls 2.14
import QtWebEngine 1.10
import QtWebChannel 1.0
ApplicationWindow {
width: 600
height: 480
visible: true
WebEngineView {
anchors.fill: parent
url: "https://www.xkcd.com"
}
Component.onCompleted: print("Completed")
Component.onStatusChanged: print("Status changed: ", status)
Component.onProgressChanged: print("Progress changed: ", progress)
}
You can't access Component properties, like status from there. You can only access the onCompleted signal because it's an "attached signal". I would use a Loader to track progress. Try it like this:
Loader {
asynchronous: true
sourceComponent: WebEngineView {
anchors.fill: parent
url: "https://www.xkcd.com"
}
onProgressChanged: {
console.log("progress: " + progress)
}
}

QtQuick button shows outside of dialog

I'm trying to make a customizable single button error message dialog in QtQuick, but when I open the dialog the "Ok" button is shown outside of it:
it looks like this
When I open the dialog again, it works normally, the button is shown at the right place.
Here is a minimal working example :
import QtQuick 2.11
import QtQuick.Window 2.11
import QtQuick.Controls 2.4
Window {
visible: true
width: 640
height: 480
Button {
text: "Open Dialog"
onClicked: {
dialog.show("This text can be customized.")
}
Dialog {
id: dialog
standardButtons: Dialog.Ok
title: "Error"
modal: true
function show(txt) {
label.text = txt
open()
}
Label {
id: label
}
}
}
}
I'm using Qt 5.11.3 with QtQuick 2.11, build target is Desktop GCC 64 bits.
Is this a bug? What am I doing wrong?
It seems to be a bug in Qt 5.11.3 or in my installation of it on Linux.
Here is the workaround I used, basically recreating the Dialog from a regular Popup :
import QtQuick 2.0
import QtQuick.Controls 2.4
import QtQuick.Layouts 1.3
Popup {
x: (parent.width-width)/2
y: (parent.height-height)/2
modal: true
closePolicy: Popup.NoAutoClose
property var title: "Error"
property var msg: ""
function show(message) {
msg = message
open()
}
ColumnLayout {
spacing: 30
Label {
Layout.alignment: Qt.AlignLeft
Layout.preferredHeight: 5
font.bold: true
text: title
}
Label {
text: msg
}
Button {
Layout.alignment: Qt.AlignRight
text: "Ok"
onClicked: {
close()
}
}
}
}

Show message dialog

Is it possible to display a QML dialog when the user hits a button in a QML window?
Example:
When the user clicks in the menu bar on Help -> About the About dialog should be displayed:
import QtQuick 2.12
import QtQuick.Layouts 1.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
import "components"
ApplicationWindow {
id: window
visible: true
width: 1040
height: 480
aboutDlg: aboutDialog {} // does not work...
menuBar: MenuBar {
Menu {
title: qsTr("Help")
MenuItem {
text: qsTr("About")
onTriggered: aboutDlg.open();
}
}
...
components/AboutDialog.qml
import QtQuick 2.2
import QtQuick.Dialogs 1.1
MessageDialog {
id: aboutDialog
title: "May I have your attention please"
text: "It's so cool that you are using Qt Quick."
onAccepted: {
console.log("And of course you could only agree.")
Qt.quit()
}
}
When I remove the line boutDlg: aboutDialog {} // does not work... the following error is reported when clicking on the About menu item:
qrc:/main.qml:61: ReferenceError: aboutDlg is not defined
How can I achieve this?
You called "aboutDialog" which is an ID in the AboutDialog.
Think of it like you add an object, like adding a Rectangle...which has its own file...and you can "instantiate" it by adding an object like so:
...
ApplicationWindow {
...
AboutDialog {
id: aboutDlg
}
...
}
You can find example HERE
You might also optimize a bit and put the AboutDialog in a Loader.

Qt's FileDialog defaultSuffix not functionning

I'm using the following code to the new property of the filedialog under QtQuick.Dialogs 1.3 & Qt 5.10.0. I've build it using Qt Creator 5.10 default kit.
import QtQuick 2.10
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.3
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
FileDialog {
id: fileDialog
title: "Please choose a file"
folder: shortcuts.home
defaultSuffix: "txt"
selectExisting: false
selectMultiple: false
onAccepted: {
console.log("You chose: " + fileUrl)
Qt.quit()
}
onRejected: {
console.log("Canceled")
Qt.quit()
}
Component.onCompleted: visible = true
}
}
My expectation are that if I choose a filename such as "MyFile", then the fileUrl would be "MyFile.txt". However it just returns "MyFile".
I have tested the code and it comes does come out with the ".txt". I am unsure of the problem but since there isn't really a question, you could append the default suffix using a global property.

Interaction between two QML files

I want to use some qml file(main.qml) but before that I need to get some authentication info from user(login, pass). So I want to do this in the second window(login.qml). I saw Qt.createComponent for opening second qml file, but I can't get any information from this type of window.
So how can I use some information from the second window in the first window?
Or how can I dynamically load these items(main.qml, login.qml) in the parent qml file?
So how can I use some information from the second window in the first
window?
This is just one way of doing it:
main.qml
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Window 2.2
import QtQuick.Layouts 1.1
ApplicationWindow {
width: 400
height: 400
visible: true
ColumnLayout {
id: logItems
height: 200
Button {
id: loginButton
onClicked: loginForm.visible = true
text: "Log in"
}
Login {
anchors.top: loginButton.bottom
id: loginForm
visible: false
onLoginInfo: {
logInfo.text = "User:" + user + " password: " + password
}
}
}
Text {
id: logInfo
anchors.top : logItems.bottom
}
}
Login.qml
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Layouts 1.1
Item {
signal loginInfo(string user, string password)
ColumnLayout {
RowLayout {
TextField {
id: user
}
TextField {
id: password
}
}
Button {
text: "Submit"
onClicked: loginInfo(user.text, password.text)
}
}
}
How can I dynamically load QML items from separate files/resources in
another QML file?
Qt.CreateComponent allows you to use JavaScript to dynamically create and use QML code from other files.

Resources