[Qt-interest] QWebView for document editing
Nathan Carter
nathancarter5 at gmail.com
Mon Jul 13 03:39:24 CEST 2009
On Jul 12, 2009, at 12:47 AM, Tony Rietwyk wrote:
> Nathan wrote:
>
>> What we do is as we generate the HTML from our model, we wrap those
>> blocks that we want to label in things of this form:
>>
>> <span id="our special id here"> ...actual content... </span>
>>
>> (or you could use div or whatever's appropriate). This flags your
>> document with the points in your model that it represents. So when
>> you get a hit in the web view, you can walk up the DOM tree to find
>> the first relevant span, get its id, and use it. I won't describe
>> that Javascript here, since I'm assuming you could build it, but if
>> you want to see it, lemme know and I'll paste our code in. It's not
>> long.
>
> Hi Nathan,
>
> Could you please send me that code snippet. Thanks!
Well the snippet that generates the HTML is highly specific to my
application. Here's the general idea. My internal data is an
OpenMath document, and I do a tree traversal on it, and after visiting
each node and recursively computing the HTML representation of the
subtree rooted at that node, I take that value (call it HTML) and do
something like this:
int n = indexOfCurrentNodeInItsParent();
HTML = QString( "<span id='OpenMath_Child_Index_%1'>%2</span>" )
.arg( n ).arg( HTML );
Then when you want to know where in the original OpenMath document the
webview cursor sits, you use
QString address = webview->page()->mainFrame()->evaluateJavaScript(
"nodeAddress( window.getSelection().focusNode )" ).toString();
assuming that all the following Javascript has already been run in
that same webview's JS engine.
function childIndexOfNode ( node )
{
if ( !( 'tagName' in node ) )
return '';
var tn = node.tagName.toLowerCase();
if ( ( tn == 'span' ) || ( tn == 'div' ) ) {
var match = /OpenMath_Child_Index_(\d+)/.exec( node.id );
if ( match && ( match.length > 0 ) )
return match[1];
}
return '';
}
function nextAncestorWithIndex ( node )
{
while ( ( typeof( node ) != 'undefined' ) && ( node != null ) ) {
if ( childIndexOfNode( node ) != '' )
return node;
node = ( 'parentNode' in node ) ? node.parentNode : null;
}
return null;
}
function nodeAddress ( node )
{
var result = '';
while ( ( typeof( node ) != 'undefined' ) && ( node != null ) ) {
var index = childIndexOfNode( node );
if ( index != '' )
result = index + ' ' + result;
node = nextAncestorWithIndex( node.parentNode );
}
return result;
}
Then I use the address, a string like '6 2 0 5 19 2 3' to walk from
the root through my original OpenMath document tree to get to the node
in question.
This is not EXACTLY what I do, but it's pretty close. It's a little
messier than this because OpenMath has attributes, too, so I have
different types of steps, not just into "child" nodes, and if you're
truly interested in the grueling details, check out these pieces of
source code.
http://sourceforge.net/apps/trac/lurch/browser/Lurch/trunk/utils/LurchLite/webviewutilities.js#L90
http://sourceforge.net/apps/trac/lurch/browser/Lurch/trunk/utils/LurchLite/alphawindow.cpp
(The latter is a mess; it's a work in progress that needs a lot of
code cleaning up! Sorry!)
> I have a similar requirement but I had problems when editing the
> nodes in
> javascript. In particular, I dod NOT want to just replace nodes with
> text
> HTML. I need to replace some of the nodes, and copy other existing
> ones (by
> ID) - which may be whole trees of nodes. But I couldn't see how to
> do this
> in a nice generic way through signals to the javascript.
I'm not sure exactly what you're saying here. But note that in
Javascript you can overwrite an entire node's content (though it be a
whole tree) with another one very easily, by calling
node.innerHTML = 'new html code here';
Then if node was a <p>, let's say, it will still be a <p>, but with
all new content (however complex) that you specified inside the string
that you assigned to innerHTML.
Is that what you meant?
Nathan
More information about the Qt-interest-old
mailing list