Disable context menu from qml in WebEngineView - qt

I'm programming a WebEngineView and I want to disable its context menu.
For what I already found I have to call QWidget's setContexMenuPolicy.
Unfortunately, all help in the Net I can find shows how to do it from C++ code, while I need to do it all from my .qml file (I have no access to the c++ code).
I tried this.setContextMenuPolicy(...) from Component.onCompleted signal inside the WebEngineView, but to no success.

I found other way, which works for my case:
WebEngineView {
anchors.fill: parent
url: "https://www.example.com"
onContextMenuRequested: {
request.accepted = true
}
}

You can't just access QWidget functions in QML if they aren't forwarded via Q_PROPERTY. You should read The Property System.
My solution is a bit of a hack. It's using a MouseArea which consumes right mouse clicks, basically blocks all right clicks on the WebEngineView:
UPDATE!
import QtQuick 2.0
import QtQuick.Window 2.0
import QtWebEngine 1.0
Window {
width: 1024
height: 750
visible: true
WebEngineView {
anchors.fill: parent
url: "https://www.qt.io"
}
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.LeftButton | Qt.MiddleButton | Qt.RightButton
onPressed: {
if (mouse.button === Qt.RightButton)
mouse.accepted = true
}
}
}

Related

How to propagateComposedEvents to Button from upper MouseArea?

Demo:
import QtQuick 2.15
import QtQuick.Controls 2.15
ApplicationWindow{
width: 500
height: 500
visible: true
Button {
text: "button"
onClicked: {
console.log("Button onClicked")
}
}
MouseArea {
anchors.fill: parent
propagateComposedEvents: true
onClicked: {
console.log("MouseArea onClicked")
mouse.accepted = false
}
}
}
I expected below when click the button
qml: MouseArea onClicked
qml: Button onClicked
but only got
qml: MouseArea onClicked
How to make the event pass to Button? and why the current demo cannot do that?
it seems a temp solution is:
import QtQuick 2.15
import QtQuick.Controls 2.15
ApplicationWindow{
width: 500
height: 500
visible: true
Button {
text: "button"
onClicked: {
console.log("Button onClicked")
}
}
MouseArea {
anchors.fill: parent
onClicked: {
console.log("MouseArea onClicked")
mouse.accepted = false
}
onPressed: {
console.log("MouseArea onPressed")
mouse.accepted = false
}
}
}
result:
qml: MouseArea onPressed
qml: Button onClicked
it is not what I want but can solve my current problem.
If this is a specific case which you are trying, one solution which you can do is to call the button clicked signal from onClicked in mouse area
import QtQuick 2.15
import QtQuick.Controls 2.15
ApplicationWindow{
width: 500
height: 500
visible: true
Button {
id:btn
text: "button"
onClicked: {
console.log("Button onClicked")
}
}
MouseArea {
anchors.fill: parent
propagateComposedEvents: true
onClicked: {
console.log("MouseArea onClicked")
btn.clicked()
}
}
}
Why the current demo cannot do that?
The point is that the order of the components in the file matters, and this order affects how they overlap each other. For example, in this case of manual positioning, we see how one component overlaps another, what is reflected in their display relative to each other. One component will overlap another component if it is located below in the code.
So in your case, it is not surprising that you get the following output:
qml: MouseArea onClicked
since the MouseArea is located after the Button, and mouse events do not reach the Button. If you arrange them in the reverse order (first the area, and then the button), then the output will be as follows:
qml: Button onClicked
How to make the event pass to Button?
If a click occurs, then it must refer to some one specific component. This means that it will not be possible to click on one component, but to process this click already in several. Therefore, in your case, you can first click on the MouseArea, and then provoke a click from the code on the Button, or vice versa.
Thus, if you want to get exactly the output that you indicated in the question, the already proposed answer will suit you. However, in this case, we lose the ability to use the standard functionality of the Button component, such as "change color when pressed", and more. So I can suggest this solution:
import QtQuick 2.15
import QtQuick.Controls 2.15
ApplicationWindow {
id: root
width: 500
height: 500
visible: true
MouseArea {
id: ma
anchors.fill: parent
propagateComposedEvents: true
onClicked: {
console.log("MouseArea onClicked")
}
Button {
text: "button"
onClicked: {
console.log("Button onClicked")
ma.clicked(ma.mouseX, ma.mouseY)
}
}
}
}
The output will look like this:
qml: Button onClicked
qml: MouseArea onPressed
However, in this case, pressing will work in two places, and at the same time the above-described functionality of the Button is preserved. You can also place the Button under the MouseArea - this will work too.

Keys.onPressed stops working when i focus else but then back to original item

im facing something which I cant explain...
I have this code:
import QtQuick 2.12
import QtQuick.Controls 2.0
import QtQuick.Controls.Styles 1.4
import QtGraphicalEffects 1.12
import QtQuick.LocalStorage 2.0
import QtMultimedia 5.15
import 'JavaScript.js' as JS
ApplicationWindow {
id: mainWindow
visible: true
width: 480 height: 800
title: qsTr("application")
Item {
id: keyboardHandler
focus: true
onFocusChanged: console.log(keyboardHandler.focus);
Keys.onPressed: { console.log(event.text; }
}
Image {
id: focusToKeyboardHandler
anchors.fill: parent
MouseArea {
anchors.fill: parent
onClicked: { keyboardHandler.focus = true; }
}
}
TextField {
id: textfieldID
}
}
and when I start the application, then all keyboard strokes properly prints into console as they should...
however if i click into the TextField, then back to image, then the keystrokes dont print anything at all :(
Why? when I click on the Image, the it properly givers me focus to keyboardHandler (proved by onFocusChanged always debugs true before i start typing... so focus on keyboardHandler is always there when needed)...
Just to be sure I have also tried to change this row to:
onClicked: { keyboardHandler.focus = true; keyboardHandler.forceActiveFocus(); }
with no luck
UPDATE: it works on physical typing onto keyboard keys... however using the barcode scanner which is HID it works only first time i start the application, not when i change focus and then back to keyboardHandler
UPDATE2: when turning application off and on works again only for the first time (or till i rechange the focus)
any ideas what could cause this?

How to run QML StateMachine example from Qt's documentation?

I'm getting back into Qt lately after a hiatus of several years, and it looks like QML is the "new hotness" these days. In the past, I've managed to get widget-based examples from Qt's documentation to work with relative ease, but... now that I'm trying to learn QML, I'm having trouble closing the gaps in the example code.
Specifically, the docs for Qt.QmlStateMachine say:
The following snippet shows a state machine that will finish when a button is clicked:
import QtQuick 2.0
import QtQml.StateMachine 1.0 as DSM
Rectangle {
Button {
anchors.fill: parent
id: button
text: "Finish state"
DSM.StateMachine {
id: stateMachine
initialState: state
running: true
DSM.State {
id: state
DSM.SignalTransition {
targetState: finalState
signal: button.clicked
}
}
DSM.FinalState {
id: finalState
}
onFinished: Qt.quit()
}
}
}
Perhaps I'm completely naive, but I thought I could just create a new Qt Quick application in QtCreator and paste the above snippet into main.qml. When I do this, though, I'm immediately confronted with an error saying:
QQmlApplicationEngine failed to load component
qrc:/main.qml:19 Button is not a type
So... I look at the docs for the QML Button type and notice that it says near the top:
Import Statement: import QtQuick.Controls 1.4
So, I add that to the top of main.qml and try to run again. And it 'works', but... there's no main window—or any other visual content whatsoever. Hmm. I guess I can see where that (maybe) makes sense, perhaps I shouldn't have replaced the entire contents of main.qml? So I decide to try retaining the Window component from the original QML supplied by QtCreator, changing my main.qml file to look like this:
import QtQuick 2.8
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
import QtQml.StateMachine 1.0 as DSM
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Rectangle {
Button {
anchors.fill: parent
id: button
text: "Finish state"
DSM.StateMachine {
id: stateMachine
initialState: state
running: true
DSM.State {
id: state1
DSM.SignalTransition {
targetState: finalState
signal: button.clicked
}
}
DSM.FinalState {
id: finalState
}
onFinished: Qt.quit()
}
}
}
}
After doing this, I see a main window when I run, but it is empty. Um... shouldn't there at least be a button in there somewhere?
Anyway, I wasn't smart enough to figure this out after almost 90 minutes of fiddling around. It seems that Qt's documentation authors are assuming a basic level of QML knowledge that I simply don't possess, so I'm unable to 'fill in the blanks'. Which is a real shame, because QML looks awesome. And I'm particularly excited to see what I can do with the declarative state machine framework! Can anybody tell me what I'm doing wrong with this particular example?
(In case it matters, I'm using Qt 5.9.2 with QtCreator 4.4.1...)
UPDATE: In his answer, #eyllanesc pointed out a small typo in the second code snippet I posted above. Where I wrote id: state1, it should have been id: state.
The documentation assumes some basic knowledge of the previous topics and in the initial paragraph: http://doc.qt.io/qt-5/qtqml-index.html gives you a list of topics that you should read and learn.
And like all language one must read the errors of the code and analyze its logic.
...main.qml:17:13: QML StateMachine: No initial state set for StateMachine
QStateMachine::start: No initial state set for machine. Refusing to start.
.../main.qml:19: ReferenceError: state is not defined
This error clearly indicates that the initial state is not recognized, and this can be caused by 2 reasons, the first is that you have not established it or the second is that you have established an inappropriate state, and in your case it is the second reason.
you have established the initial state:
initialState: state
but state does not exist, I think you wanted to place state1
initialState: state1
The button is not shown because you have established that its size is the same as that of the parent: anchors.fill: parent, and Button's parent is Rectangle, and if Rectangle is not set a size will have a size of 0, causing the son to have it too. A possible solution is to establish Rectangle the size of the parent:
import QtQuick 2.8
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
import QtQml.StateMachine 1.0 as DSM
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Rectangle {
anchors.fill: parent
Button {
anchors.fill: parent
id: button
text: "Finish state"
DSM.StateMachine {
id: stateMachine
initialState: state1
running: true
DSM.State {
id: state1
DSM.SignalTransition {
targetState: finalState
signal: button.clicked
}
}
DSM.FinalState {
id: finalState
}
onFinished: Qt.quit()
}
}
}
}
or not use Rectangle:
import QtQuick 2.8
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
import QtQml.StateMachine 1.0 as DSM
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Button {
anchors.fill: parent
id: button
text: "Finish state"
DSM.StateMachine {
id: stateMachine
initialState: state1
running: true
DSM.State {
id: state1
DSM.SignalTransition {
targetState: finalState
signal: button.clicked
}
}
DSM.FinalState {
id: finalState
}
onFinished: Qt.quit()
}
}
}

How to use QML Connect{} with Qt Creator Design Mode

The below code works fine in Qt Creator Edit Mode, but when I try to switch to Design Mode it gives an error:
"Can not open this qml document because of an error in the qml file."
And then I can't edit the layout graphically. If I comment out the Connect{} item then Design Mode works again and I can edit graphically.
Anybody see what the error might be.
What am I doin wrong? Thanks for looking.
import QtQuick 2.4
import QtQuick.Window 2.2
Window {
id: window1
visible: true
Rectangle {
id: rect
color: "#ffffff"
width: 100; height: 100
MouseArea {
id: mouseArea
anchors.fill: parent
}
Connections {
target: mouseArea
onClicked: {
print("clicked")
}
}
}
}

QML - MouseArea - propagating onPositionChanged

Is it possible to propagate a MouseArea's positionChanged event to an underlying one?
I've tried to set the mouse.accepted to false for any existing signal handler of the top-most MouseArea as well as setting the propagateComposedEvents to true. Neither of those worked (although I'm not surprised with the propagateComposedEvents not working since the documentation says it only relays events like clicked, doubleClicked and pressAndHold).
Depending on your structure you can always manually propagate the event by having your onPositionChanged handler call underlyingMouseArea.positionChanged(mouse) This should manually emit the signal in the underlying MouseArea. My only concern is that you might not be able to pass a MouseEvent object this way(never tried with anything other than a string). However, you can always perform this manual emit in C++ which definetly would not suffer from any type conversion issues.
Unless you need to handle position change events with multiple mouse areas simultaneously you could try reparent your top mouse area:
import QtQuick 2.2
import QtQuick.Layouts 1.1
Rectangle {
id: __root
color: "lightgreen"
width: 360
height: 360
Rectangle {
id: rect2
width: 100; height: 100
color: "cyan"
MouseArea {
parent: __root // set 'logical' parent
anchors.fill: rect2 // set 'visual' ancestor
hoverEnabled: true
onPositionChanged: {
console.log('mouse area 2 onPositionChanged');
}
}
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
onPositionChanged: {
console.log('mouse area 1 onPositionChanged');
}
}
}
There is an unresolved bugreport.

Resources