QtWebView. How to enable page scrolling and scrolling elements on a page (e.g. Google Maps)

I encountered a problem with a white list web browser that my company is developing / supporting for one of our products. The browser runs on top of Qt 4.8.6 using qtwebkit (migrating to 5.X would be ideal, but the built-in Linux OS we use is too old to support newer versions based on our testing and upgrading to a newer OS version is too expensive for us / our customers). The primary browser interface is a 6x8 touch screen mounted inside the cockpit.

For sites that have things like scrollable / embedded maps (e.g. Google Maps), browser users want to drag the whole page when they select something outside the map, and drag only the map (without the whole scroll of the page) when selected map (Ala - most popular mobile browsers).

So far, I could do one or the other, but not both:

  • When I bind mouse handlers to QWebView or QGraphicsWebView, I can turn the cursor into a hand and it’s very easy to support dragging and dropping the entire web page. However, this blocks the ability of the page to handle mouse events when the user draws a map (i.e. when the user drags the map, it drags the entire page without moving the map).

  • When I don't add mouse events to hooks for processing events, things like maps can be scrolled by grabbing / dragging them, but of course, the user loses the ability to drag the whole page.

Currently, the browser uses later versions, with the scroll bars disabled and the directional arrow overlaid to allow the user to scroll the entire page (since the screen size is limited and the scroll bars take up too much space when they are large enough for the user to interact with them) ... but it's not perfect.

My question is: is there an easy way to do this so that the page and elements on the page can be easily scrolled?

Thanks! Rob

+5
source share
1 answer

It seems to me that you need to check whether you are above such a map and ignore (pass) the event in this case. I think you should do something like this:

bool GraphicsWebView::isOverMap(QPoint pos) { QWebPage* webPage = this->page(); if (webPage) { QWebFrame* webFrame = webPage->frameAt(pos); if (webFrame) { QString selectorQuery = "#map-canvas"; // Based on https://developers.google.com/maps/tutorials/fundamentals/adding-a-google-map QList<QWebElement> list = webFrame->findAllElements(selectorQuery).toList(); // Find all the maps! foreach(QWebElement element, list) { if (element.geometry().contains(pos)) { return true; // Cursor is over a map } } } } return false; // No match } 

Obviously, this is a rather specific function, but there is probably a way to get a better selector query that will apply to all of these QWebElement types.

Assuming you hook mouse events by subclassing QGraphicsWebView and overriding void mouseMoveEvent(QGraphicsSceneMouseEvent * event) , I suggest you do something like:

 void GraphicsWebView::mouseMoveEvent(QGraphicsSceneMouseEvent* event) { if (isOverMap(mapFromScene(event->scenePos()).toPoint())) { // We got a map! event.ignore(); // Clear the accept flag return; // Return, we're done here } handleMoveView(); // Not over any maps, let scroll the page } 

This part of the document explains how events are processed with respect to the topmost element. I especially recommend you read the third paragraph.

Hope this helps!

EDIT: A bit more research, and it looks like something like this might be more general: graphicsView.focusItem()->flags().testFlag(QGraphicsItem::ItemIsMovable);

This is at least worth considering as a replacement for isOverMap()

EDIT: Gotcha, here is what you can try. Start by subclassing QGraphicsSceneMouseEvent and add a signal named void destroyedWithoutAccept() , which is emitted in the destructor if the event is not accepted.

Then change mouseMoveEvent to look like this:

 void GraphicsWebView::mouseMoveEvent(QGraphicsSceneMouseEvent* event) { MyEvent myEvent = new MyEvent(event); // Copy event event.accept(); // accept original event connect(myEvent, SIGNAL(destroyedWithoutAccept), this, SLOT(handleMoveView)); // Callback if unused QGraphicsWebView::mouseMoveEvent(myEvent); // Pass it to Base class } 

If this works, it may cause a delay if deleteLater is used to destroy it. But in this case also override it.

+2
source

Source: https://habr.com/ru/post/1211196/


All Articles