PDA

View Full Version : How to set QWebEngineView on QQuickView



ejoshva
8th May 2015, 12:58
I am porting from QGraphicsView to QQuickView.

Like we load QGraphicsWebView on QGraphicsView, how to load QWebEngineView on QQuickView.

currently I am setting it like below but it's not getting loaded.


QuickViewReader::QuickViewReader(QWindow *parent): QQuickView(parent)
{
WebView = new WebEngineView();
root = new QQmlContext(engine.rootContext());
qmlRegisterType<WebEngineView>("WebView", 1,0, "WebEngineView");

/* Setting the current object into context of QML source */
root->setContextProperty("rw", this);
this->rootContext()->setContextProperty("rw", this);
/* Setting the webview object into context of QML source */
root->setContextProperty("webView",this->WebView);

QQmlComponent component(&engine);
component.loadUrl(QUrl("qrc:/ReaderView.qml"));
object = component.create(root);

setSource(QUrl("qrc:/ReaderView.qml"));
setResizeMode(QQuickView::SizeRootObjectToView);
}

The page is blank.
When I explicitly call WebView.show(), the page is displayed.

How to overlay QWebEngineView on QQuickView

wysota
8th May 2015, 13:22
What is this WebEngineView class?

ejoshva
8th May 2015, 13:38
I find that QQuickView is QWindow type and QWebEngineView is QWidget type.

QQuickView , I am making use of extensively to enable the QML functionalities.

To display the page alone, QWebEngineView I am using and also for actions made on that page like highlight, annotation, search, mouseWheelRoll etc.

Added after 14 minutes:

Also found that, there is QQuickWidget which is of QWidget type.

So I will have to use QQuickWidget only?? or I can proceed with using QQuickView.

Basically I use this QQuickView for QML functionality only.

wysota
8th May 2015, 13:39
You didn't answer my question.

ejoshva
8th May 2015, 13:49
its inherited class from QWebEngineView

anda_skoa
8th May 2015, 13:57
No need to register anything, QtWebEngine has a QML module:
http://doc.qt.io/qt-5/qtwebengine-index.html

Cheers,
_

ejoshva
9th May 2015, 06:29
Actually I am porting from QDeclarativeView to QWebEngineView, So QGraphicsWebView is placed inside QDeclarativeView. I wanted to implement a similar thing.

I have modified QDeclarativeView to QQuickWidget and QGraphicsWebView to QWebEngine.

QDeclarativeView has toolbar , next/prev button to navigate and pageslider bar. QGraphicsWebView is to display the page and capture events on the page and do related functionality like Highlight,Annnotations.....

How to implement a similar in QQuickWidget and QWebEngineView.

ejoshva
9th May 2015, 08:30
No need to register anything, QtWebEngine has a QML module:
http://doc.qt.io/qt-5/qtwebengine-index.html

Cheers,
_

In the example provided in the link,


import QtQuick 2.1
import QtQuick.Controls 1.1
import QtWebEngine 1.0

ApplicationWindow {
width: 1280
height: 720
visible: true
WebEngineView {
id: webview
url: "http://www.qt-project.org"
anchors.fill: parent
}
}


How is this accessed in WebEngineView.cpp (inherited from QWebEngineView)
or How to set these elements from WebEngineView onto QML

wysota
9th May 2015, 09:11
How to implement a similar in QQuickWidget and QWebEngineView.

It will be extremely difficult to do that. However you can start with what anda_skoa suggested -- instead of registering your own custom web engine view, use the one that is already available.


How is this accessed in WebEngineView.cpp (inherited from QWebEngineView)

"This"? As in "current object"?


or How to set these elements from WebEngineView onto QML
"These" elements? What elements?

anda_skoa
9th May 2015, 14:28
How to set these elements from WebEngineView onto QML

The example is QML code, there no need to set any element.
The WebEngineView element is provided by the QtWebEngine module without any effort needed on the application developer's side.

Just use it as any other QtQuick item.

Cheers,
_

ejoshva
11th May 2015, 04:21
Thanks for your replies @ anda_skoa and @ wysota

Let me try implement your suggestions.

ejoshva
11th May 2015, 07:09
I have done as below and I am able to invoke.


Main.qml

ApplicationWindow {
title: qsTr("diacritech")
width: 1200
height: 800
visible: true
WebEngineView {
id: webview
url: "http://www.google.co.in"
anchors.fill: parent
}
}

WebEngineView.cpp
WebEngineView::WebEngineView()
{
QQmlEngine engine;
QQmlContext *objectContext = new QQmlContext(engine.rootContext());
objectContext->setContextProperty("we",this);
QQmlComponent component(&engine);
component.loadUrl(QUrl("qrc:/main.qml"));
QObject *object = component.create(objectContext);

}

main.cpp
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
WebEngineView *weView = new WebEngineView();
weView->show();

return app.exec();
}


Here I get 2 windows, 1. WebEngienView() 2. QML -> WebEngineView

When I comment the webengineview.show() in main.cpp, I am getting only one window.
Is this the way, this is to be done?

Also I am including another components of another QML file (ReaderToolBar.qml). The tool bar is displayed but I am not able to capture the mouseclick events


Main.qml (included below component)


ReaderToolBar {
id: tb
width: parent.width
height: 50
anchors.top: parent.top
color: "transparent"
}



Is there something I am missing, which enables to capture the mouse click events?

wysota
11th May 2015, 07:18
What is it exactly that you are trying to achieve?

anda_skoa
11th May 2015, 07:28
How about you start with the basic setup and then extend it once it works.

So on C++ side just


int main(int argc, char **argv)
{
QApplication app(argc, argv);

QQuickView view;
view.setSource(QUrl("qrc:/main.qml");
view.show();

return app.exec();
}


And you can set your toolbar directly as the ApplicationWindow's toolBar property


ApplicationWindow {
toolBar: ReaderToolBar { ... }
}


Cheers,
_

ejoshva
11th May 2015, 07:30
I am porting from QGraphicsView to QWebEngineView. Already there are QMLs written for tool bar and other related functions like highlight list, annotations list, searchilist etc

Now I have to include those QML components in the WebEngineView QML.

wysota
11th May 2015, 07:32
I am porting from QGraphicsView to QWebEngineView.
Yes, we already know that. And that's actually the only thing we know. But what are you porting?


Now I have to include those QML components in the WebEngineView QML.

What do you mean that you have to include them in WebEngineView? Did you implement them in HTML? What do you use QML for?

ejoshva
11th May 2015, 07:42
What I am porting is actually a e-book reader (where in each page will be html/xhtml).

The page is displayed with WebEngineView, tool bar is super imposed on the WebEngineView.
The images for each functions like highlights, annotations, library etc are images on the tool bar. Onclick of the image, the onlick event is captured in corresponding QML component and respective functions in CPP file is called to process them.

wysota
11th May 2015, 10:14
I still fail to see what you are using QML for.

ejoshva
11th May 2015, 10:38
QML is used to display tool bar , list box etc which will be superimposed on the QWebEngineView.

QML basically acts like an intermediate between the user input( like mouse onlick event) and the QWebEngineView.




WebEngineView::WebEngineView()
{
QQmlEngine engine;
QQmlContext *objectContext = new QQmlContext(engine.rootContext());
objectContext->setContextProperty("we",this);

QQmlComponent component(&engine);
component.loadUrl(QUrl("qrc:/ToolBar.qml"));

QObject *object = component.create(objectContext);

this->setUrl(QUrl("http://www.google.co.in"));

}


In the above code, I have set the Url for the QWebEngineView.
I want to display the toolbar using the QML (QML component) over this QWebEngineView page. (just like adding layers in photoshop)

wysota
11th May 2015, 10:59
Your above code makes no sense, you create a local qml engine that immediately goes out of scope.

If you want to super-impose two qml objects then position them in the same area:

Item {
WebEngineView {
anchors.fill: parent
}

ReaderToolBar {
anchors: { left: parent.left; right: parent.right; top: parent.top }
}

}

ejoshva
11th May 2015, 12:10
When I have the webengineview in QML, is it possible for SetHtml(). This is because the the html pages are in local storage and in encrypted format.
In the code, I will decrypt and set the page using SetHtml().

Otherwise, is it possible possible to superimpose the ReaderToolBar.qml over WebEngineView.cpp which will make the setHtml() easier.

wysota
11th May 2015, 12:38
When I have the webengineview in QML, is it possible for SetHtml(). This is because the the html pages are in local storage and in encrypted format.
In the code, I will decrypt and set the page using SetHtml().

Otherwise, is it possible possible to superimpose the ReaderToolBar.qml over WebEngineView.cpp which will make the setHtml() easier.

WebEngineView has a url method that takes the url of a resource to be loaded. The resource is loaded via QNetworkAccessManager bound to the QML engine. You can control that engine and there you can decrypt the data.

Remember that QWebEngineView is a widget, not a Qt Quick element, you cannot simply put it on a Qt Quick scene.

ejoshva
11th May 2015, 13:30
@wysota , I will try to implement just as u suggested

Meanwhile, I tried something like the below, here only the 2nd widget added (weview) alone is displayed. When I comment out, lay->addWidget(weView); ReaderToolBar is displayed.



WebEngineView *weView = new WebEngineView();
weView->setGeometry(55,0,1000,750);
weView->show();
QQuickView view;
view.setSource(QUrl("qrc:/ReaderToolBar.qml"));
view.setGeometry(0,0,1200,50);
view.show();
QVBoxLayout *lay = new QVBoxLayout();
lay->addWidget(QWidget::createWindowContainer(&view));
lay->addWidget(weView);
QWidget *wid = new QWidget();
wid->setLayout(lay);
wid->resize(1200,800);
wid->show();


What I am doing wrong here.

ejoshva
12th May 2015, 06:35
How about you start with the basic setup and then extend it once it works.

So on C++ side just


int main(int argc, char **argv)
{
QApplication app(argc, argv);

QQuickView view;
view.setSource(QUrl("qrc:/main.qml");
view.show();

return app.exec();
}


And you can set your toolbar directly as the ApplicationWindow's toolBar property


ApplicationWindow {
toolBar: ReaderToolBar { ... }
}


Cheers,
_

I am trying to implement this but I am getting error as
component errors : (qrc:/Main.qml:18:13: Invalid attached object assignment)



import QtQuick 2.4
import QtQuick.Controls 1.3
import QtWebEngine 1.0


ApplicationWindow {
title: qsTr("diacritech")
width: 1200
height: 800
visible: true

WebEngineView {
id: currentwebview
objectName: "webView"
url: "http://www.google.co.in"
anchors.fill: parent

ToolBar :readTool
}
function showPage(content,baseUrl)
{
//console.log(content);
//console.log(baseUrl)
currentwebview.loadHtml(content,baseUrl)
}
ReaderToolBar {
width: parent.width
height: 50
id : readTool
// anchors: { left: parent.left; right: parent.right; top: parent.top }

}
}

wysota
12th May 2015, 06:38
Line 18 doesn't make sense. Compare anda_skoa's code and yours. And look up functionality that you use in API docs instead of blindly trying things hoping it would work.

anda_skoa
12th May 2015, 07:42
This is because the the html pages are in local storage and in encrypted format.
In the code, I will decrypt and set the page using SetHtml().

Wouldn't it be a lot easier to just write the content to a temporary file and pass the URL to that to the view?

Cheers,
_

ejoshva
12th May 2015, 07:54
Wouldn't it be a lot easier to just write the content to a temporary file and pass the URL to that to the view?

Cheers,
_

if it's one or two pages, then its fine I guess. But I will have whole book say 500 pages to show. If I am showing only one page at a time then not a problem. I have reflow layout means , I will just keep scrolling and pages will be shown.

currently I have written the qml like below, it's displaying the tool bar over the webengineview and next /previous buttons are also displayed.
The issue now is that the click events are not detected for the next/previous or elements on tool bar. Is there something, I should include to capture the click events.



ApplicationWindow {
title: qsTr("diacritech")
width: 1200
height: 800
visible: true

WebEngineView {
id: currentwebview
objectName: "webView"
url: "http://www.google.co.in"
anchors.fill: parent

}

toolBar: ReaderToolBar {
id: tb
width: 1400
height: 50
//anchors.top: parent
// color: "transparent"
MouseArea {
anchors.fill: parent
onClicked: console.log("clicked tool bar")
}
}
function showPage(content,baseUrl)
{
currentwebview.loadHtml(content,baseUrl)
}

Image {
id: prevPage
width: 50
height: 50
anchors.top: parent.top
anchors.left: parent.left
anchors.leftMargin: 20
anchors.topMargin: (parent.height / 2 ) - 40
source: "images/prev_button.png"
visible: true
MouseArea {
anchors.fill: parent
onClicked:{ console.log("Clicked previous page")}
}
}

Image {
id: nextPage
width: 50
height: 50
anchors.top: parent.top
anchors.right: parent.right
anchors.rightMargin: 1
anchors.topMargin: (parent.height / 2 ) - 40
source: "images/next_button.png"
visible: true
MouseArea {
anchors.fill: parent
onClicked: console.log("clicked nextpage")
}
}
}

wysota
12th May 2015, 08:55
How is ReaderToolBar defined?

anda_skoa
12th May 2015, 09:16
if it's one or two pages, then its fine I guess. But I will have whole book say 500 pages to show. If I am showing only one page at a time then not a problem. I have reflow layout means , I will just keep scrolling and pages will be shown.


One other option might be to just load a basic HTML document with an embedded display section (frame, whatever) and get the content through a web sockets connection with the host application (or using QtWebChannel).

Cheers,
_

ejoshva
12th May 2015, 09:57
How is ReaderToolBar defined?



import QtQuick 2.0

Rectangle{
id: tbrect
width: 1200
height: 50
// color: "transparent"
visible: true

MouseArea {
anchors.fill: parent
hoverEnabled: true
}
function showicons()
{
libicon.visible = true
}
Image {
id: libicon
x: 30
smooth: true
height: 36
width: 36
anchors.bottom: parent.bottom
anchors.bottomMargin: 8
source: "qrc:/images/library.png"
visible: true

MouseArea {
id: libiconma
anchors.fill: parent
onClicked: {

//rw.showlibrary()
console.log("library")
}
}
}
Component.onCompleted: showicons()
}

wysota
12th May 2015, 10:00
You have covered your toolbar with another mouse area so events are not reaching the ones inside the tool bar.

ejoshva
12th May 2015, 11:17
click event in the prevpage/nextpage is also not caught :(

Actually the ones inside the tool bar is not detected so I wrote a mousearea in the main.qml, where it's used.

Added after 52 minutes:

When I have the QML as Application window, I am able to set the page to display for webengineview using setHtml().
But when it's Rectangle, I am not able to set the page using SetHtml().

I have used QQuickWidget and using setSource()


ReaderView.cpp ( inherits QQuickWidget)
ReaderView::ReaderView()
{
setSource(QUrl("qrc:/Main.qml"));
QQmlEngine engine;
QQmlComponent component(&engine);
component.loadUrl(QUrl("qrc:/Main.qml"));
QObject *object = component.create();
Decrypt *decrypt = new Decrypt();
QString content = decrypt->decryptFile("/Users/user/learnOnContent/LifeSciences_Grade1020151518_1963/Pages/pag001.html", 'A');
QUrl baseUrl = QUrl("file:///Users/user/ssparklBookStore/LifeSciences_Grade1020151518_1963/Pages/pag001.html");
QMetaObject::invokeMethod(object, "showPage", Q_ARG(QVariant, content),Q_ARG(QVariant, baseUrl));
}

Main.qml
Rectangle {
id : readview
width: 1200
height: 800
visible: true
WebEngineView {
id: currentWebView
url: "http://www.google.co.in"
anchors.fill: parent
}
function showPage(content,baseUrl)
{
currentWebView.loadHtml(content,baseUrl)
}

ReaderToolBar {
id: tb
width: 1400
height: 50
//anchors.top: parent
color: "transparent"
}
}


showPage(content,baseUrl) is getting called but webEngineView is displaying only google.com and not the page set by setHtml()

anda_skoa
12th May 2015, 15:44
I would recommend to expose the HTML as a property on a context object instead.

Then you can do something like


WebEngineView {
readonly property string htmlContent: contextObject.htmlProperty
onHtmlContentChanged: loadHtml(htmlContent, contextObject.baseUrl);
}


Cheers,
_

ejoshva
13th May 2015, 05:50
WebEngineView {
id: currentWebView
url: "http://www.google.co.in"
anchors.fill: parent
readonly property string htmlContent: readView.getHtmlContent()
onHtmlContentChanged: loadHtml(htmlContent, readView.getBaseUrl());
}



ReaderView::ReaderView()
{
setSource(QUrl("qrc:/Main.qml"));
QQmlEngine engine;
QQmlContext *context = new QQmlContext(engine.rootContext());
context->setContextProperty("readView",this);
QQmlComponent component(&engine);
component.loadUrl(QUrl("qrc:/Main.qml"));
QObject *object = component.create(context);
}


Getting error as
qrc:/Main.qml:18: ReferenceError: readView is not defined
qrc:/Main.qml:18: TypeError: Property 'getHtmlContent' of object QQuickWidget(0x7f9d5a49f7b0) is not a function

wysota
13th May 2015, 06:32
What is the base class of ReaderView?

anda_skoa
13th May 2015, 07:33
WebEngineView {
id: currentWebView
url: "http://www.google.co.in"
anchors.fill: parent
readonly property string htmlContent: readView.getHtmlContent()
onHtmlContentChanged: loadHtml(htmlContent, readView.getBaseUrl());
}


My recommendation is to use a property, not a function.
Otherwise this is a one time thing, the onHtmlContentChanged will only be invoked on the very first assignment.
You want to be able to push new HTML, which would be automatic with properties.

QML automatically reevaluates expressions that contain properties when any of these properties change, so called property bindings.

It also seems strange that you would want to destroy the QQmlEngine right after creating and using it. Don't you want to keep your QML parts running during the applicatino life time?

Cheers,
_

ejoshva
13th May 2015, 08:04
What is the base class of ReaderView?

QQuickWidgets

Added after 15 minutes:

@anda_skoa
you mean to set a property in qml like


property string htmldata : rdView.getHtmlContent()
WebEngineView {
id: currentWebView
url: "http://www.google.co.in"
anchors.fill: parent
readonly property string htmlContent: htmldata
onHtmlContentChanged: loadHtml(htmlContent, readView.getBaseUrl());
}


or I will have to set the property in cpp and then use it over hear. In that case, how to set the property ?

Kindly pardon for my ignorance

wysota
13th May 2015, 09:18
QQuickWidgets

So why are you instantiating a new QML engine and loading the same QML document twice?

ejoshva
13th May 2015, 14:01
I didn't realize that. Thanks for pointing out that.
Now have modified it.



ReaderView::ReaderView()
{

QQmlContext *context = new QQmlContext(this->rootContext());
context->setContextProperty("rdView",this);
context->setContextProperty("content",content);
setSource(QUrl("qrc:/Main.qml"));
}

WebEngineView {
id: currentWebView
url: "http://www.google.co.in"
anchors.fill: parent
readonly property string htmlContent: content
onHtmlContentChanged: loadHtml(htmlContent, rdView.getBaseUrl());
}



But I am getting error as
qrc:/Main.qml:18: ReferenceError: content is not defined
qrc:/Main.qml:19: TypeError: Property 'getBaseUrl' of object QQuickWidget(0x7fe328f0eb40) is not a function
qrc:/Main.qml:18: ReferenceError: content is not defined

Not sure, what I am missing :(

Added after 7 minutes:

Got it working by setting as property.



WebEngineView {
id: currentWebView
url: "http://www.google.co.in"
anchors.fill: parent
readonly property string htmlContent: content
onHtmlContentChanged: loadHtml(htmlContent, baseUrl);
}

ReaderView::ReaderView()
{
Decrypt *decrypt = new Decrypt();
QString content = decrypt->decryptFile("/Users/user/learnOnContent/LifeSciences_Grade1020151518_1963/Pages/pag001.html", 'A');
setHtmlContent(content);
QUrl baseUrl = QUrl("file:///Users/user/ssparklBookStore/LifeSciences_Grade1020151518_1963/Pages/pag001.html");
setBaseUrl(baseUrl);

QQmlContext *context = this->rootContext();
context->setContextProperty("rdView",this);
QVariant qv(content);
context->setContextProperty("content",qv);
context->setContextProperty("baseUrl",baseUrl);
setSource(QUrl("qrc:/Main.qml"));
}


Thanks anda_skoa

anda_skoa
13th May 2015, 18:24
or I will have to set the property in cpp and then use it over hear. In that case, how to set the property ?

Have a Q_PROPERTY on the object you are exporting.

This is the easiest way of having changable content exported from C++ .
Whenever your C++ code needs QML to update its bindings, it just emits the property's change notification signal.
See comment #33 on how that looks from QML.



class ReaderView : // whatever your base class is
{
Q_OBJECT
Q_PROPERTY(QString content READ content NOTIFY contentChanged)
public:

QString content() const: // that is the part after READ above

signals:
void contentChanged();
};

So whenever you emit contentChanged(), the property "content" (that's the part before READ) will be reevaluated, by QQmlEngine calling the property's READ function content().

Cheers,
_

ejoshva
14th May 2015, 06:02
ReaderView.h
class ReaderView : public QQuickWidget
{
Q_OBJECT
Q_PROPERTY(QString content READ content NOTIFY contentChanged)
public:
ReaderView();
~ReaderView();
QString content() const;
void setContent(const QString &value) {
if (value != htmlContent) {
htmlContent = value;
emit contentChanged();
}
}
signals:
void contentChanged();
public slots:
QUrl getBaseUrl() const;
void setBaseUrl(const QUrl &value);

private :
QString htmlContent;
QUrl baseUrl;
};

ReaderView.cpp
ReaderView::ReaderView()
{
Decrypt *decrypt = new Decrypt();
QString content = decrypt->decryptFile("/Users/user/learnOnContent/LifeSciences_Grade1020151518_1963/Pages/pag001.html", 'A');
setHtmlContent(content);
QUrl baseUrl = QUrl("file:///Users/user/ssparklBookStore/LifeSciences_Grade1020151518_1963/Pages/pag001.html");
setBaseUrl(baseUrl);

QQmlContext *context = this->rootContext();
context->setContextProperty("rdView",this);
setSource(QUrl("qrc:/Main.qml"));
}

Main.qml
WebEngineView {
id: currentWebView
// url: "http://www.google.co.in"
anchors.fill: parent
readonly property string htmlContent: rdView.content
onHtmlContentChanged: loadHtml(htmlContent, rdView.getBaseUrl());
}


Now getting error as
UUndefined symbols for architecture x86_64:
"vtable for ReaderView", referenced from:
ReaderView::ReaderView() in ReaderView.o
ReaderView::~ReaderView() in ReaderView.o
NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Added after 10 minutes:

Got the issue resolved.

Issue was with .pro file.

Missed adding QT += gui

wysota
14th May 2015, 07:26
Got the issue resolved.

Issue was with .pro file.

Missed adding QT += gui

Are you sure it wasn't that you didn't define body for constructor and destructor?

ejoshva
14th May 2015, 07:33
@wysota: I am sure, missing "gui" in pro file was the issue. Constructor and destructor body I have added. Even in the code sample pasted here is constructor.

anda_skoa
14th May 2015, 07:42
The vtable error usually means that you did not re-run qmake after adding Q_OBJECT to a class that had already been part of the project.

Btw, why not make the baseUrl a property as well?

Cheers,
_

ejoshva
14th May 2015, 08:01
Yes, I have to make base url property as well.

Thanks anda_skoa and wysota for your values inputs.

I have implemented mouseMoveEvent in WebEngineView class.

But after reading from the internet QTBUG-43602 (https://bugreports.qt.io/browse/QTBUG-43602) and from one of your posts (http://www.qtcentre.org/threads/62149-Mouseevents-on-a-QwebView-or-WebEngineView) got to know that QWebEngineView doesn't capture mouseEvents and it's a limitation.

Also suggestion was given as to monitor QObject::childEvent of the QWebEngineView and install an event filter when a new child QWidget appear during page loads

how do I do this?

ejoshva
14th May 2015, 10:35
I tried implement eventfilter by installing it. But mouse events are not captured in the event()->type.

How to capture the mouseevent in qwebengineview

wysota
14th May 2015, 11:11
What did you install the event filter on?

ejoshva
14th May 2015, 11:21
ReaderMain::ReaderMain(QWidget *parent)
: QQuickWidget(parent)
{
webView = new WebEngineView(this);
tool = new toolbar(this);
this->installEventFilter(webView);
}

bool WebEngineView::eventFilter(QObject *obj, QEvent *event)
{
qDebug()<<obj->metaObject()->className() <<" : "<<event->type();

if(event->type() == QEvent::MouseButtonPress)
{
qDebug()<<"mouse press";
}
}


The mouse events are of value 2,3,4,5. But I dont receive these events only window focus, window enable, window disable events (12,25,25) events are received.

What I want to actually do is on click drag and release (meaning some text), I want to display a menu where option will be shown as to highlight or annotation.

wysota
14th May 2015, 12:13
Are you sure you know what you are doing? How is your webView object related to WebEngineView declaration you have (or at least had yesterday) in your QML document?

ejoshva
14th May 2015, 12:29
Yesterday I was trying out with QML for WebEngineView.

Now the code is different, I will be using that QML WebEngineView at later point of time.

Currently I am doing as bellow




WebEngineView::WebEngineView(QWidget *parent)
: QWebEngineView(parent)
{
setEnabled(true);
setGeometry(0,0,dw.width(),dw.height());
decrypt = new Decrypt();
setPageContent(decrypt->decryptFile("/Users/user/learnOnContent/LifeSciences_Grade1020151518_1963/Pages/pag002.html", 'A'));
setUrl(QUrl("file:///Users/user/ssparklBookStore/LifeSciences_Grade1020151518_1963/Pages/pag002.html"));
loadCurrentPage();
prev = new QPushButton(this);
prev->setGeometry(30,(dw.height()/2)-50,50,50);
prev->setStyleSheet("border:1px");
prev->setIcon(QIcon(QString::fromUtf8(":/images/prev_button.png")));
prev->setIconSize(QSize(50, 50));

next = new QPushButton(this);
next->setGeometry(dw.width()-90,(dw.height()/2)-50,50,50);
next->setStyleSheet("border:1px");
next->setIcon(QIcon(QString::fromUtf8(":/images/next_button.png")));
next->setIconSize(QSize(50, 50));
connect(prev,SIGNAL(clicked()),this,SLOT(loadPrevi ousPage()));
connect(next,SIGNAL(clicked()),this,SLOT(loadNextP age()));

}


toolbar::toolbar(QWidget *parent) : QQuickWidget(parent)
{
QQmlContext *objectContext = this->rootContext();
objectContext->setContextProperty("tb", this);
setSource(QUrl("qrc:/ReaderToolBar.qml"));
setResizeMode(QQuickWidget::SizeRootObjectToView);
}


ReaderMain::ReaderMain(QWidget *parent)
: QQuickWidget(parent)
{
webView = new WebEngineView(this);
tool = new toolbar(this);

// this->installEventFilter(webView);

this->hideToolBarWid(true);
tool->setStyleSheet("background-color: transparent;");
connect(tool, SIGNAL(s_showlib()), this, SLOT(showlibrary()));
connect(tool,SIGNAL(s_showTOCFromTB()), this, SLOT(showtocinwebview()));
connect(tool,SIGNAL(s_fixLayout()),this,SLOT(loadf xlayout()));
connect(tool, SIGNAL(s_showreflow()), this, SLOT(loadflowpage()));
connect(tool, SIGNAL(s_hideToolBar(bool)), this, SLOT(hideToolBarWid(bool)));
}



currently I am using this way.

Here I would want to capture the mouse events on the WebEngineView

wysota
14th May 2015, 13:28
Installing an event filter on the webview doesn't make sense. The bug report you mentioned said you had to do it on a child of the view.

ejoshva
15th May 2015, 05:14
Yes Wysota. But I am not sure how to implement that. :(

wysota
15th May 2015, 06:28
I believe it is described in the report.

ejoshva
16th May 2015, 10:56
childEvent (http://doc.qt.io/qt-5/qobject.html#childEvent) link gives details regarding QWebEngineView::childEvent.
But I am not getting how to implement this.
Please provide some sample code, how to implement this childEvent().

wysota
16th May 2015, 12:18
childEvent (http://doc.qt.io/qt-5/qobject.html#childEvent) link gives details regarding QWebEngineView::childEvent.
But I am not getting how to implement this.
Please provide some sample code, how to implement this childEvent().

Do you understand what you need to do? Or is the next question you ask going to be "what do I put there?" and the next one "please provide me with a sample code of an event filter"?

ejoshva
18th May 2015, 05:56
I have written the code for event filter, What I am not clear is how to implement as child of the WebEngineView.
I have said this in few post earlier as well.

Now I have written the eventFilter() in the class which as inherited QWebEngineView, so that makes it the child class. But I don't get the events for mouse.
So what is this child class supposed to be?

wysota
18th May 2015, 06:33
I have written the code for event filter, What I am not clear is how to implement as child of the WebEngineView.
What do you not understand? Did you read the docs on what childEvent() does? Did you go through the docs of QChildEvent? What options does it present?


Now I have written the eventFilter() in the class which as inherited QWebEngineView, so that makes it the child class. But I don't get the events for mouse.

Which clearly indicates you have no idea what the problem is and what you are supposed to do with it.

Child of object A is an object B for whom A is set as its QObject::parent(). childEvent lets you be notified when a child object (B) is added or removed from a particular object (A) which lets you install an event filter (on B).

ejoshva
15th June 2015, 10:16
Below is the code in which I have implemented the childEvent.
I am able to catch the mouse events



#include "WebEngineView.h"

WebEngineView::WebEngineView(QWidget *parent)
: QWebEngineView(parent)
{
installEventFilter(this);
setEnabled(true);
setGeometry(0,0,dw.width(),dw.height());
load(QUrl("http://www.thehindu.com"));
}

WebEngineView::~WebEngineView()
{

}

bool WebEngineView::eventFilter(QObject *obj, QEvent *event)
{

switch(event->type())
{
case QEvent::ChildAdded:
{
QChildEvent* ce = static_cast<QChildEvent*>(event);
// Install the filter to each new child object created
ce->child()->installEventFilter(this);
break;
}
case QEvent::ChildRemoved:
{
QChildEvent* ce = static_cast<QChildEvent*>(event);
// Remove the the filter from each new child object removed
ce->child()->removeEventFilter(this);
break;
}
case QEvent::MouseButtonPress:
{
QMouseEvent* me = static_cast<QMouseEvent*>(event);
if (me->button() == Qt::LeftButton)
{
event->accept();
}
if (me->button() == Qt::RightButton)
{
event->accept();
}
break;
}
case QEvent::MouseButtonRelease:
{
QMouseEvent* me = static_cast<QMouseEvent*>(event);
qDebug()<<"selected Text : "<<this->selectedText();
break;
}
case QEvent::MouseMove:
{
QMouseEvent* me = static_cast<QMouseEvent*>(event);
break;
}
case QEvent::MouseButtonDblClick:
{
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
if (mouseEvent && mouseEvent->button() == Qt::LeftButton)
{
qDebug()<<"clicked position : " << mouseEvent->pos();
}
else if (event->type() == QEvent::Wheel)
{
QWheelEvent *wheelEvent = static_cast<QWheelEvent*>(event);
if (wheelEvent->buttons() == Qt::RightButton)
{
event->ignore();
return false;
}
if (wheelEvent->modifiers().testFlag(Qt::ControlModifier))
{
event->accept();
break;
}
}
}
default:

}
return QWidget::eventFilter(obj, event);
}

ejoshva
2nd July 2015, 14:02
How to get the selected text from page loaded in the WebEngineView which is loaded as QML element.
(i.e.) just as we get page()->selectedText() from the QWebEngineView.



//ReaderView.qml
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtWebEngine 1.0

Rectangle {
id: rect1
height: 600
color: "white"


WebEngineView {
id: currentWebview
objectName: "webView"
url: "http://www.google.co.in"
anchors.fill: parent
readonly property string htmlContent: content
onHtmlContentChanged: loadHtml(htmlContent, baseUrl);
MouseArea {
anchors.fill: parent
onClicked: {
console.log("clicked")
}
onPressed: {
console.log("x="+mouseX)
console.log("y="+mouseY)
}
onReleased: {
console.log("release x: "+mouseX)
console.log("release y: "+mouseY)
}

}
}
}

//ReadWidget.cpp
readwidget::readwidget(QWidget *parent) : QQuickWidget(parent)
{
engine = QQuickWidget::engine();
root = this->rootContext();

/* Setting the current object into context of QML source */
root->setContextProperty("rw", this);

/*Initializing the variables for the usage in QML*/
Decrypt *decrypt = new Decrypt();
QString content = decrypt->decryptFile("/Users/user/ssparklContent/LifeSciences_Grade1020151518_1963/Pages/10_chap05.html", 'A');

QUrl baseUrl = QUrl("file:///Users/user/ssparklContent/LifeSciences_Grade1020151518_1963/Pages/10_chap05.html");
QVariant pgContent(content);

root->setContextProperty("content",pgContent);
root->setContextProperty("baseUrl",baseUrl);


/* Setting the QML source as ReaderView.qml to be executed from
* current object */
setSource(QUrl("qrc:/ReaderView.qml"));
QQmlComponent component(engine);
component.loadUrl(QUrl("qrc:/ReaderView.qml"));
object = component.create(root);

setResizeMode(QQuickWidget::SizeRootObjectToView);

}

anda_skoa
2nd July 2015, 16:21
Maybe there is a way to do that through running JavaScript in the Web context?
I.e. calling runJavaScript() with some script code that uses "browser" methods of getting the selected text?

Something like



runJavaScript("window.getSelection()", function(result) { console.log("selected Text=" + result);} );


Cheers,
_

ejoshva
3rd July 2015, 06:49
Thanks anda_skoa.
But the problem now I am facing is that I am not able to select itself. only click events are detected in the WebEngineView (QML) after adding the mouse area to the WebEngineView
Is there some restriction as in QWebEngineView in detecting MouseEvents.

anda_skoa
3rd July 2015, 08:18
I am afraid I don't understand.

Are you saying that the web view does not handle user mouse interaction such that the user can select text?

Cheers,
_

ejoshva
3rd July 2015, 10:36
included the 'drag' in the mousearea and now I am able to select text



WebEngineView {
id: currentWebview
objectName: "webView"
url: "http://www.google.co.in"
anchors.fill: parent
readonly property string htmlContent: content
onHtmlContentChanged: loadHtml(htmlContent, baseUrl);

MouseArea {
id : mousearea
anchors.fill: parent
drag {
target: currentWebview
axis: Drag.XandYAxis
}

onPressed: {
pressPoint.x = mouseX
pressPoint.y = mouseY

}
onReleased: {
releasePoint.x = mouseX
releasePoint.y = mouseY
console.log(releasePoint)
}
}
onXChanged: {
if(mousearea.drag.active){
console.log("x : "+x)
currentWebview.runJavaScript("window.getSelection()", function(result) { console.log("selected Text=" + result);} )
}
}

}


But I dont find any prints which I intended using console.log

I am not find the drag to be consistant. Since, for 2 executions, I am able to select the text and the next execution it's not selectable. When I execute again, it's selectable.

When the text is selected, no prints are got. when it's not selectable. prints are got.

anda_skoa
3rd July 2015, 10:59
I don't understand your example.
You are dragging the web view? how is that related to selection of text?

Cheers,
_

ejoshva
3rd July 2015, 11:45
I didn't intend to drag the webview instead, I want to capture the mouse drag event and the text selection.
So what should be the target in that case to enable selection.

wysota
3rd July 2015, 11:50
Selection should work out of the box.

ejoshva
3rd July 2015, 13:06
It was working before including the mousearea inside WebEngineView.
After including mousearea for WebEngineView, only clicks are available. Selection is non-existent.

Added after 1 2 minutes:

I am trying to use QWebEngineView as extended through qmlregistertype and not as QtWebEngine element WebEngineView as below



//ReaderView.qml
import QtQuick 2.4
import QtQuick.Controls 1.3
import WebView 1.0

Rectangle {
id: rect1
height: 800
width : 1300
color: "white"


WebEngineView {
id: currentWebview
height : parent.height
width : parent.width
}
}

//ReadWidget.cpp
readwidget::readwidget(QWidget *parent) : QQuickWidget(parent)
{
engine = QQuickWidget::engine();
root = this->rootContext();

/* Setting the current object into context of QML source */
root->setContextProperty("rw", this);

/*Initializing the variables for the usage in QML*/
Decrypt *decrypt = new Decrypt();
QString content = decrypt->decryptFile("/Users/user/ssparklContent/LifeSciences_Grade1020151518_1963/Pages/10_chap05.html", 'A');

QUrl baseUrl = QUrl("file:///Users/user/ssparklContent/LifeSciences_Grade1020151518_1963/Pages/10_chap05.html");
QVariant pgContent(content);

root->setContextProperty("content",pgContent);
root->setContextProperty("baseUrl",baseUrl);
qmlRegisterType<webview>("WebView", 1,0, "WebEngineView");

/* Setting the QML source as ReaderView.qml to be executed from
* current object */
setSource(QUrl("qrc:/ReaderView.qml"));
QQmlComponent component(engine);
component.loadUrl(QUrl("qrc:/ReaderView.qml"));
object = component.create(root);

setResizeMode(QQuickWidget::SizeRootObjectToView);

}


here getting error as below
Invalid property assignment: "height" is a read-only property
Invalid property assignment: "width" is a read-only property

anda_skoa
3rd July 2015, 13:32
It was working before including the mousearea inside WebEngineView.
After including mousearea for WebEngineView, only clicks are available. Selection is non-existent.

What do you need the MouseArea for?
Your code snippet doesn't say much in that regard.



I
I am trying to use QWebEngineView as extended through qmlregistertype and not as QtWebEngine element WebEngineView as below

I think we've covered that in some other thread already (or it was someone with a very similar setup): QWebEngineView is a widget.
It can (a) not be embedded in a QtQuick2 scene and (b) has no writable x/y/width/height properties (only writable geometry).

Cheers,
_

ejoshva
3rd July 2015, 14:19
What do you need the MouseArea for?
Your code snippet doesn't say much in that regard.

I want to replicate the mouseEvents that we have in the QWebEngineView (i.e.) highlight the selected text, scroll to view the searched text on the page.

Exact requirement is on mouse release, I will show a context Menu (highlight, annot). On selecting highlight, the selected text will be highlighted, on selecting annot, annot text box will open up for user input; also the selected text will be highlighted.

I will also be doing a search on the page by getting user input, upon finding the word on the page have to scroll that line to viewable part of the screen.




I think we've covered that in some other thread already (or it was someone with a very similar setup): QWebEngineView is a widget.
It can (a) not be embedded in a QtQuick2 scene and (b) has no writable x/y/width/height properties (only writable geometry).

by bad
missed the part. I remember this one.

wysota
3rd July 2015, 14:23
Let's summarize the current situation. What exactly are you using as your web view? What exactly does the scene look like? What is the relation between the web view item and the MouseArea item (if any)? And finally, what is the ultimate goal you are trying to achieve?

ejoshva
4th July 2015, 01:16
Let's summarize the current situation. What exactly are you using as your web view?
QtWebEngine
QML WebEngineView

What exactly does the scene look like?
There is a QQuickWidget in which Qml is included using setSource().
this QML has the QtWebEngine's element WebEngineView defined in it.

What is the relation between the web view item and the MouseArea item (if any)?
I want to emulate the QMouseEvents of the WebView in the Qml WebEngineView.
So included the MouseArea to capture the mouse events.

And finally, what is the ultimate goal you are trying to achieve?
What I am trying to achieve is to show a context Menu (highlight, annot) on mouse drag release (selecting text on the page loaded on the WebEngineView). On selecting highlight, the selected text will be highlighted, on selecting annot, annot text box will open up for user input; also the selected text will be highlighted.

I will also be doing a search on the page by getting user input, upon finding the word on the page have to scroll that line to viewable part of the screen.

wysota
4th July 2015, 06:42
I want to emulate the QMouseEvents of the WebView in the Qml WebEngineView.
So included the MouseArea to capture the mouse events.
What do you mean by that? WebEngineView already handles mouse events without any additional items on top of it.



What I am trying to achieve is to show a context Menu (highlight, annot) on mouse drag release (selecting text on the page loaded on the WebEngineView).
On "mouse drag release" or rather when text selection on a page changes? What if someone selects text by double or tripple clicking?

Does that help you in any way?

http://forums.mozillazine.org/viewtopic.php?f=25&t=198568


On selecting highlight, the selected text will be highlighted, on selecting annot, annot text box will open up for user input; also the selected text will be highlighted.
What is annot? What HTML element is used to display that on a web page?


I will also be doing a search on the page by getting user input, upon finding the word on the page have to scroll that line to viewable part of the screen.

I don't think WebEngineView contains API that could do it.

Tell me one more thing, why are you using Qt Quick at all if you just have a single static item on the scene? QWebEngineView has much richer API and subclassing it would probably let you use much more of its functionality.

ejoshva
4th July 2015, 07:08
What do you mean by that? WebEngineView already handles mouse events without any additional items on top of it.
In that case, how do I do the customized action like what can be done on mouseReleaseEvent(), mousePressEvent().


On "mouse drag release" or rather when text selection on a page changes? What if someone selects text by double or tripple clicking?
Does that help you in any way?
http://forums.mozillazine.org/viewtopic.php?f=25&t=198568.
I am taking into account the text selection only on single click, hold, drag to select the text and release.

What is annot? What HTML element is used to display that on a web page?.
Annotation, I have the code to display the annotations.


I don't think WebEngineView contains API that could do it..
For search too, have implemented functions to do the same.


Tell me one more thing, why are you using Qt Quick at all if you just have a single static item on the scene? QWebEngineView has much richer API and subclassing it would probably let you use much more of its functionality.
I have much more items on the ReaderView.qml, WebEngineView is just an item.

In nutshell, I am trying to do a e-reader but in real it's browser where in html or xhtml pages are loaded. But the functionalities of the e-reader are implemented.

wysota
4th July 2015, 08:39
In that case, how do I do the customized action like what can be done on mouseReleaseEvent(), mousePressEvent().
You put a mouse area over the item and handle things there. But you don't have to repeat what the view already handles itself. Just pass in the events you are not handling yourself in the mouse area.


Annotation, I have the code to display the annotations.
Shouldn't you be implementing everything in HTML then?


For search too, have implemented functions to do the same.
Where did you implement that?


I have much more items on the ReaderView.qml, WebEngineView is just an item.
Telling one thing in one post and then telling a different thing in another post doesn't help to solve the problem:



What exactly does the scene look like?
There is a QQuickWidget in which Qml is included using setSource().
this QML has the QtWebEngine's element WebEngineView defined in it.


In nutshell, I am trying to do a e-reader but in real it's browser where in html or xhtml pages are loaded. But the functionalities of the e-reader are implemented.
IMO all you want can easily be done in HTML which you already have instead of struggling to do it in Qt Quick. You can equip your page with required facilities to communicate with Qt Quick (e.g. using QWebChannel), do the things which are simple to do in HTML and pass enough information to Qt Quick to do the rest there (e.g. show a context menu).

ejoshva
4th July 2015, 08:54
I have implemented that search in C++.

Regarding mouse Events, I am not able to find how to do this


You put a mouse area over the item and handle things there. But you don't have to repeat what the view already handles itself. Just pass in the events you are not handling yourself in the mouse area.


If I am doing everything in HTML, nativity will be a problem.

wysota
4th July 2015, 09:29
I have implemented that search in C++.
And how did you merge that with WebEngineView?


Regarding mouse Events, I am not able to find how to do this
Either ignore the events you don't handle yourself and/or configure MouseArea to only react to a subset of buttons. Events for remaining buttons will be ignored automatically.


If I am doing everything in HTML, nativity will be a problem.
I have no idea what you mean by that.

anda_skoa
4th July 2015, 09:47
Regarding mouse Events, I am not able to find how to do this


I think if you set the "accepted" property of the MouseEvent to "false" it will be passed onto the item below the mouse area.

Cheers,
_

ejoshva
7th July 2015, 12:18
Below is my WebEngineView (QML) . If the selection is enabled, then this mousearea is not considered. When the mousearea is active, selection is inactive.

I dont understand, why fewer times, mousearea defined inside WebEngineView is enabled and rest of times mousearea defined is not enabled.




WebEngineView {
id: currentWebview
objectName: "webView"
url: "http://www.google.co.in"
anchors.fill: parent
readonly property string htmlContent: content
onHtmlContentChanged: loadHtml(htmlContent, baseUrl);

MouseArea {
id : mousearea
anchors.fill: parent
drag {
id : weDrag
target: currentWebview
}

onPressed: {
pressPoint.x = mouseX
pressPoint.y = mouseY
console.log("PressPoint : "+pressPoint)
}
onReleased: {
releasePoint.x = mouseX
releasePoint.y = mouseY
console.log("releasePoint : "+releasePoint)
if(pressPoint != releasePoint )
{
currentWebview.runJavaScript("window.getSelection()", function(result) { console.log("selected Text=" + result);} )
}
}
}
}


Added after 10 minutes:


You put a mouse area over the item and handle things there. But you don't have to repeat what the view already handles itself. Just pass in the events you are not handling yourself in the mouse area.


how do pass in the events which I am not handling.
in QGraphicsWebView, we pass in the mouse events as QGraphicsWebView::mousePresses(event).

Here how do I do the same.

Also I am not able to capture the selected text.
how can I do that.


onReleased: {
releasePoint.x = mouseX
releasePoint.y = mouseY
console.log("releasePoint : "+releasePoint)
if(pressPoint != releasePoint )
{
currentWebview.runJavaScript("window.getSelection()", function(result) { console.log("selected Text=" + result);} )
}
}


I tried something as above, when this signal is captured, selection is not enabled.
When selection is enabled, this signal (ie) mousearea defined is not enabled

anda_skoa
7th July 2015, 12:21
So letting the events pass by setting their accepted flag to false did not work?

Cheers,
_

ejoshva
7th July 2015, 12:26
onPressed: {
pressPoint.x = mouseX
pressPoint.y = mouseY
console.log("PressPoint : "+pressPoint)
acceptedButtons : false

}


This is how I did and it didn't work.

wysota
7th July 2015, 12:57
That's not what anda_skoa had in mind. You were supposed to set "accepted" property of the event object to false.

onPressed: { mouse.accepted = false }

ejoshva
7th July 2015, 13:20
after including this code, the mousearea itself is not enabled.

Please let me know, how to capture enable text selection through MouseArea and this MouseArea to be always enabled.

anda_skoa
7th July 2015, 13:46
text selection is done by the web view element, not by the mouse area.
the idea was to pass the events through to the view for its selection handling.

Cheers,
_

ejoshva
8th July 2015, 04:58
text selection is done by the web view element, not by the mouse area.
the idea was to pass the events through to the view for its selection handling.

Cheers,
_

In that case, the control doesn't reach the mousearea when I include the mouse.accept = false.

if it's handled by the webview element, on which signal of the webview element I can catch the selection

wysota
8th July 2015, 07:29
In that case, the control doesn't reach the mousearea when I include the mouse.accept = false.
You mean this doesn't work?

WebEngineView {
anchors.fill: parent

MouseArea {
anchors.fill: parent

onClicked: {
console.log("I was clicked at "+mouse.x+"x"+mouse.y)
mouse.accepted = false
}
}
}


if it's handled by the webview element, on which signal of the webview element I can catch the selection
WebEngineView does not have such signal, I think I already said so a couple of posts ago.

ejoshva
8th July 2015, 08:03
WebEngineView {
id: currentWebview
objectName: "webView"
//url: "http://www.google.co.in"
anchors.fill: parent
readonly property string htmlContent: content
onHtmlContentChanged: loadHtml(htmlContent, baseUrl);

MouseArea {
id : mousearea
anchors.fill: parent

drag {
target: currentWebview
axis : "XAndYAxis"
active: true
}

onPressed: {
pressPoint.x = mouseX
pressPoint.y = mouseY
console.log("PressPoint : "+pressPoint)

}
onReleased: {
releasePoint.x = mouseX
releasePoint.y = mouseY
console.log("releasePoint : "+releasePoint)
if(pressPoint != releasePoint )
{
mouse.accepted = false
currentWebview.runJavaScript("window.getSelection()", function(result) { console.log("selected Text=" + result);} )
}
}

}
}



The code is as above and logs got are
qml: PressPoint : QPointF(513, 101)
qml: releasePoint : QPointF(716, 99)
qml: selected Text=[object Object]


the selected text is just object because text selection was disabled.

how do I get the text there.

wysota
8th July 2015, 08:08
drag {
target: currentWebview
axis : "XAndYAxis"
active: true
}

Why do you insist on keeping this code? It doesn't do what you think it does.


the selected text is just object because text selection was disabled.
The selected text is an object because everything in JavaScript is an object.

https://developer.mozilla.org/en-US/docs/Web/API/Window/getSelection

anda_skoa
8th July 2015, 08:24
In that case, the control doesn't reach the mousearea when I include the mouse.accept = false.

Which of the events do you get and do not accept and which ones do you not get at all?

Cheers,
_

ejoshva
8th July 2015, 10:17
Which of the events do you get and do not accept and which ones do you not get at all?

Cheers,
_

none of the events defined in mousearea was caught when selection is enabled.

When selection is disabled, all the events of the mousearea are got

wysota
8th July 2015, 10:18
Please show the exact code you used for testing this.

This works for me without problems:

import QtWebEngine 1.0
import QtQuick 2.4


WebEngineView {
url: "http://www.google.com"

MouseArea {
anchors.fill: parent

onPressed: {
console.log("Pressed: "+mouse.x+"x"+mouse.y)
mouse.accepted = false
}

}
}

ejoshva
8th July 2015, 10:52
Why do you insist on keeping this code? It doesn't do what you think it does.


The selected text is an object because everything in JavaScript is an object.

https://developer.mozilla.org/en-US/docs/Web/API/Window/getSelection

thanks for pointing it out Wysota.
Will remove that code.

Now I am not able to select any text. Just that I drag it over the text area.

Added after 33 minutes:




WebEngineView {
id: currentWebview
objectName: "webView"
//url: "http://www.google.co.in"
anchors.fill: parent
readonly property string htmlContent: content
onHtmlContentChanged: loadHtml(htmlContent, baseUrl);

MouseArea {
id : mousearea
anchors.fill: parent

onPressed: {
pressPoint.x = mouseX
pressPoint.y = mouseY
console.log("PressPoint : "+pressPoint)

}
onReleased: {
releasePoint.x = mouseX
releasePoint.y = mouseY
console.log("releasePoint : "+releasePoint)
if(pressPoint != releasePoint )
{
mouse.accepted = false
currentWebview.runJavaScript("window.getSelection()", function(result) { console.log("selected Text =" + result.toString());} )
}
}

}
}


This is the code used for testing that.

Now I get the signals onPressed, onReleased in the mousearea.


but the text selection is unavailable. Just that I can drag the mouse.

anda_skoa
8th July 2015, 13:21
Now I get the signals onPressed, onReleased in the mousearea.


but the text selection is unavailable. Just that I can drag the mouse.
What if you do not accept the events?

Cheers,
_

wysota
8th July 2015, 14:39
Now I get the signals onPressed, onReleased in the mousearea.


but the text selection is unavailable. Just that I can drag the mouse.

You are not ignoring the events. Only an ignored event will be propagated to an item below the mouse area. This is all in the docs, please read it instead of wasting your time for meaningless problems.

ejoshva
9th July 2015, 05:41
What if you do not accept the events?

Cheers,
_

I am not able to find any difference.

the problem I face here is that the text selection is not available. I don't find the cursor itself, just the mouse pointer which means only clicks are allowed and selection is not allowed.

Yes, there has been quite a few posts about me stating selection not available . But I am not able to understand what you are trying to convery :crying:

Added after 4 minutes:


You are not ignoring the events. Only an ignored event will be propagated to an item below the mouse area. This is all in the docs, please read it instead of wasting your time for meaningless problems.

All I need here is the text selection, can you please tell me. how do I do that. There has quite a few posts, you stating it's handled by WebEngineView itself. But after implementing MouseArea, there is only mouse pointer and not cursor that means only clicks are allowed and not selection. can you please tell me how to make text selection available.

wysota
9th July 2015, 06:09
All I need here is the text selection, can you please tell me. how do I do that.
I already told you, I even gave you a working example (post #90) which you silently ignored and another one earlier (#85) which you didn't comment as well.


can you please tell me how to make text selection available.
Don't do anything. It works by default. However I think you want something else -- you want a mouse area over an item and still have items reach the webview. For that, as said many times already, events need to be ignored (accepted = false) in the mouse area. Nobody will do that for you -- you have to decide yourself which events to consume in the mouse area and which to pass to the underlying item.

Wow... we are going to reach 100 posts in this thread...

ejoshva
9th July 2015, 07:17
I already told you, I even gave you a working example (post #90) which you silently ignored and another one earlier (#85) which you didn't comment as well.


I didn't intend to ignore you post.
For the post#90, I replied with the code which you asked for.
Also post #85 I have included.

Below is the current code and have also attached the screen of what I trying to do.


//ContextMenu.qml
import QtQuick 2.0

Rectangle {
id : cxtMenu
width: 140
height: 24
radius: width*0.5
color: "#222222"
Image {
id: triangle
height: 15
width: 15
anchors.top: parent.top
anchors.topMargin: 24
anchors.horizontalCenter: parent.horizontalCenter
smooth: true
source: "qrc:/images/triangle.png"
visible: true
}
Rectangle {
id:hglt
height: 24
width: 60
radius: width*0.1
anchors.top : parent.top
anchors.left: parent.left
border.color: "#000000"
border.width: 0
color: "#222222"

Text {
id:hglttext
text: qsTr("Highlight")
font.pointSize: 11
font.family: "san-serif"
anchors.left: parent.left
anchors.leftMargin: 10
anchors.top: parent.top
anchors.topMargin: 5
smooth: true
color: "#CFCFCF"
MouseArea {
anchors.fill: parent
onClicked: {
browserwindow.cxtMenu()
}
}
}
}
Rectangle {
id:verticalline
height: parent.height
width: 1
anchors.top :parent.top
anchors.left: parent.left
anchors.leftMargin: 70
color: "#CFCFCF"
}

Rectangle {
id:annot
height: 24
width: 80
radius: width*0.1
anchors.top : parent.top
anchors.left: parent.left
anchors.leftMargin: 71
border.color: "#000000"
border.width: 0
color: "#222222"

Text {
id:annottext
text: qsTr("Annotation")
font.pointSize: 11
font.family: "san-serif"
anchors.left: parent.left
anchors.leftMargin: 10
anchors.top: parent.top
anchors.topMargin: 5
smooth: true
color: "#CFCFCF"
MouseArea {
anchors.fill: parent
onClicked: {
browserwindow.newnotes()
}
}
}
}
}


//BrowserWindow.qml
import QtQuick 2.0
import QtQuick.Controls 1.3
import QtWebEngine 1.0


Rectangle {
id:flick
height: parent.height
width: parent.width - 5
property variant mypoint: Qt.point(10,10)
property variant pressPoint: Qt.point(10,10)
property variant releasePoint: Qt.point(10,10)
property string pagecontents: ""
property string url: ""
WebEngineView {
id: currentWebview
objectName: "webView"
//url: "http://www.google.co.in"
anchors.fill: parent
readonly property string htmlContent: content
onHtmlContentChanged: loadHtml(htmlContent, baseUrl);

MouseArea {
id : mousearea
anchors.fill: parent

onPressed: {
pressPoint.x = mouseX
pressPoint.y = mouseY
console.log("PressPoint : "+pressPoint)

}
onReleased: {
releasePoint.x = mouseX
releasePoint.y = mouseY
console.log("releasePoint : "+releasePoint)
if(pressPoint != releasePoint )
{
mouse.accepted = false
currentWebview.runJavaScript("window.getSelection()", function(result) { console.log("selected Text =" + result.toString());} )
cntxtMenu.visible = true
cntxtMenu.x = mouseX - 80
cntxtMenu.y = mouseY - 38
}
}

}
}
}


11263
What I am trying to do is. on mouse release will bring in a context menu to highlight the selected text or add annotation to selected text

Don't do anything. It works by default. However I think you want something else -- you want a mouse area over an item and still have items reach the webview. For that, as said many times already, events need to be ignored (accepted = false) in the mouse area. Nobody will do that for you -- you have to decide yourself which events to consume in the mouse area and which to pass to the underlying item

Yes, without including the mousearea selection was available. After including the mousearea only selection is unavailable.
I am confused to choose which event needs to be ignored to make the text selection available.


Wow... we are going to reach 100 posts in this thread...
Thx Wysota and anda_skoa for your continuous guidance and help. Without you both, I wouldn't have been able to reach where I am now. Thanks a ton.
Hope, I would be able to complete what I am trying with your help.

anda_skoa
9th July 2015, 08:12
Below is the current code and have also attached the screen of what I trying to do.


onPressed: {
pressPoint.x = mouseX
pressPoint.y = mouseY
console.log("PressPoint : "+pressPoint)

}


Can you point out in which of these lines you are calling mouse.accept = false?

I keep looking at the code and can't find it. Is it in some invisible font in the line after console.log?

Cheers,
_

wysota
9th July 2015, 08:24
Can you point out in which of these lines you are calling mouse.accept = false?

I keep looking at the code and can't find it. Is it in some invisible font in the line after console.log?

I was meaning to ask the same thing.

ejoshva
9th July 2015, 09:58
I was meaning to ask the same thing.

I have included in OnReleased


onReleased: {
releasePoint.x = mouseX
releasePoint.y = mouseY
console.log("releasePoint : "+releasePoint)
if(pressPoint != releasePoint )
{
mouse.accepted = false
currentWebview.runJavaScript("window.getSelection()", function(result) { console.log("selected Text =" + result.toString());} )
cntxtMenu.visible = true
cntxtMenu.x = mouseX - 80
cntxtMenu.y = mouseY - 38
}
}


I understood as only I am doing something customised alone I will have to include mouse.accepted = false. In mousePressed, I am not doing anything customised, just storing the value.,

anda_skoa
9th July 2015, 10:04
Well, if you don't pass the press event to the web view, how is the web view supposed to start drag selection?

Cheers,
_

wysota
9th July 2015, 10:54
I have included in OnReleased

If an object doesn't get a "pressed" signal, it will not receive a "released" signal. Only an object which accepted a 'pressed' signal will get it. You have to pass the 'pressed' signal for selection to work.

ejoshva
9th July 2015, 11:52
WebEngineView {
id: currentWebview
objectName: "webView"
anchors.fill: parent
readonly property string htmlContent: content
onHtmlContentChanged: loadHtml(htmlContent, baseUrl);

MouseArea {
id : mousearea
anchors.fill: parent

onPressed: {
pressPoint.x = mouseX
pressPoint.y = mouseY
mouse.accepted = true
}
onReleased: {
releasePoint.x = mouseX
releasePoint.y = mouseY
if(pressPoint != releasePoint )
{
cntxtMenu.x = releasePoint.x - 74
cntxtMenu.y = releasePoint.y - 30
cntxtMenu.visible = true
mouse.accepted = true
currentWebview.runJavaScript("window.getSelection()", function(result) { console.log("selected Text =" + result.toString());} )
}
}
}
}


I have included as accepted = true, still I dont get the selection :(

Added after 45 minutes:


If an object doesn't get a "pressed" signal, it will not receive a "released" signal. Only an object which accepted a 'pressed' signal will get it. You have to pass the 'pressed' signal for selection to work.

I have included the mouse.pressed = true in mousePressed as well, still selection not available :(

anda_skoa
9th July 2015, 12:20
I have included the mouse.pressed = true in mousePressed as well, still selection not available :(

I don't know, in all languages that I know about, the meaning of "true" is not the same meaning as "false".
It is definitely not the case for JavaScript.

Cheers,
_

ejoshva
9th July 2015, 12:21
to pass on to webview, it should be true as per the docs.

I will have to define by own logic, when I set it to false.

I kept mouse.accepted = false for both mousepressed and mousereleased, then the selection is available.

Now how to get the text selection meaning on which event? since the control doesn't reach mousearea.

once selection is done, I will have to bring up the context menu.

Which event should be captured??

on WebView or mousearea, I should look to capture the drag event.

the text is selected on the page loaded on webview, (i.e.) it's child rite. May be I am wrong in this.

anda_skoa
9th July 2015, 14:54
to pass on to webview, it should be true as per the docs.

Which docs?




I kept mouse.accepted = false for both mousepressed and mousereleased, then the selection is available.

As expected



Now how to get the text selection meaning on which event? since the control doesn't reach mousearea.

What "control" doesn't reach mouse area?



once selection is done, I will have to bring up the context menu.
Which event should be captured??

Mouse Release ends the selection, no?
So you get the release first, you set up a delayed trigger, you let the event pass to the web view, you get the selection in the delayed trigger.



on WebView or mousearea, I should look to capture the drag event.

No, drag is something entirely different.

Cheers,
_

ejoshva
10th July 2015, 04:50
Which docs?
mouseevent#accepted (http://doc.qt.io/qt-4.8/qml-mouseevent.html#accepted-prop)

What "control" doesn't reach mouse area?
I have capture the mousePressed point and trying to compare that with the mouseRelease point to bring up the context menu.
But I am not able to capture the mousePressed Point in the mousePressed event defined in the MouseArea.



Mouse Release ends the selection, no?
So you get the release first, you set up a delayed trigger, you let the event pass to the web view, you get the selection in the delayed trigger.

I have already included ContextMenu.visible = true in OnReleased.
But it doesn't show up when the accepted is false.

When the accepted is false, whatever I write in mouseArea events like onpressed, onreleased doesn't get executed.

In that case, where do I have to capture them. Please bare with me for asking this again.

What is a delayed trigger ?




No, drag is something entirely different.
Yes I get it.

wysota
10th July 2015, 07:27
mouseevent#accepted (http://doc.qt.io/qt-4.8/qml-mouseevent.html#accepted-prop)

Let me quote these docs and highlight the relevant part: Setting accepted to true prevents the mouse event from being propagated to items below this item.


I have capture the mousePressed point and trying to compare that with the mouseRelease point to bring up the context menu.
What for? Does the decision of showing a context menu depend on the distance between press and release?


But I am not able to capture the mousePressed Point in the mousePressed event defined in the MouseArea.
Why not? I think my example code demonstrates how to do that.


I have already included ContextMenu.visible = true in OnReleased.
But it doesn't show up when the accepted is false.
What do you mean? Does the code execute but does nothing or does the code not execute at all? I would expect that onReleased of the overlay MouseArea might not execute if you cleared the accepted flag on the press event because of what I said a couple of posts earlier. Did you verify that?


When the accepted is false, whatever I write in mouseArea events like onpressed, onreleased doesn't get executed.
Did you run my example from post #90? Can you modify my example to demonstrate that?

ejoshva
10th July 2015, 10:22
What for? Does the decision of showing a context menu depend on the distance between press and release?
Yes, if the pressed point and released point are not same, I will show the context menu at the released point.


Why not? I think my example code demonstrates how to do that.
Even from your example, I get only the mousePressed event.


What do you mean? Does the code execute but does nothing or does the code not execute at all? I would expect that onReleased of the overlay MouseArea might not execute if you cleared the accepted flag on the press event because of what I said a couple of posts earlier. Did you verify that?

I control doesnt reach the mouseReleased event itself. Only in mouseReleased, I am setting it to visible.



Did you run my example from post #90? Can you modify my example to demonstrate that?
[/QUOTE] yes, 11265

Have attached the whole project making use of the QML code you gave.

Here the control reaches the mousePressed event alone. It doesn't reach the mouseReleased event.

What I am doing is, if the mouse pressed point and mouse released point are not same, and if the selected text is not empty, will show the context menu.

wysota
10th July 2015, 10:47
Yes, if the pressed point and released point are not same, I will show the context menu at the released point.
And if they are the same?


Even from your example, I get only the mousePressed event.
The point is that you do get it.


I control doesnt reach the mouseReleased event itself. Only in mouseReleased, I am setting it to visible.
If it is not the same item which accepted mousePressEvent, it will not get mouseReleaseEvent.


Here the control reaches the mousePressed event alone. It doesn't reach the mouseReleased event.
Last time you said it didn't reach mousePressed :)


What I am doing is, if the mouse pressed point and mouse released point are not same, and if the selected text is not empty, will show the context menu.
Why can't you do that from the HTML page like I suggested some number of posts earlier? It is much easier to get the presses there and then transmit that information to QtQuick so that it can show a context menu.

ejoshva
10th July 2015, 10:57
And if they are the same? not gonna do anything with it unless, it's a link.



The point is that you do get it.
yes I get it



If it is not the same item which accepted mousePressEvent, it will not get mouseReleaseEvent.
didn't get you. here mousearea is the item which accepted mousePressEvent and same mousearea only accepting mouseReleaseEvent.
I am getting confused
Is it that when I say mouse.accepted = false in onPressed event, I wont get the control in onReleased event??



Last time you said it didn't reach mousePressed :) my bad, I had given the print after the accepted = false.



Why can't you do that from the HTML page like I suggested some number of posts earlier? It is much easier to get the presses there and then transmit that information to QtQuick so that it can show a context menu.
The code is already there, as I have said many posts back, I am porting from QGraphicsWebView to WebEngineView.
There are some thousand html pages already created.To change all the html pages, its difficult . May be for future ones can include.
I have to make use of existing code of the app alone and can't make changes to existing html pages

wysota
10th July 2015, 16:14
The code is already there, as I have said many posts back, I am porting from QGraphicsWebView to WebEngineView.
There are some thousand html pages already created.To change all the html pages, its difficult .
You don't have to do that. There is this nice "runJavaScript" method in WebEngineView which lets you execute arbitrary script any time you want.

ejoshva
11th July 2015, 05:11
so you mean to say that, after setting the mouse.accepted = false in onPressed event, I cant have some code executed in onReleased event ??

even if I am executing javacript, when will I capture it? on the webengineview to bring up the contextmenu qml.


can you please help to bring up in this flow only rather than bringing up a new one.

wysota
11th July 2015, 09:07
so you mean to say that, after setting the mouse.accepted = false in onPressed event, I cant have some code executed in onReleased event ??
It seems so. I think you could install an event filter on the element instead and intercept those events before they reach the webview without using a mouse area but that's much more complicated than what you are currently doing.


even if I am executing javacript, when will I capture it? on the webengineview to bring up the contextmenu qml.

The web component needs to have a mechanism (such as QWebChannel I mentioned earlier) that lets you communicate with Qt Quick. When you detect a press, a release and do your logic, simply tell Qt Quick to open the context menu.


can you please help to bring up in this flow only rather than bringing up a new one.
I don't understand what you mean.