Drag and drop data van JavaScript naar C++ doorgeven

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • cenix
  • Registratie: September 2001
  • Laatst online: 16:17
Ik probeer vanuit JavaScript via een Qt webkit bridge een C++ object te bedienen. De webkit bridge is functioneel, maar ik krijg vanuit een drag 'n drop niet de juiste informatie door.

De aanroep naar de betreffende methode gaat goed, alleen krijg ik ipv een IP adres, de string "1" door. Na inspectie blijkt het IP adres wel in het geheugen te staan (met 4 bytes per character, gezien een IP adres denk ik aan UTF-32). Alerts binnen de JS omgeving retourneren wel het juiste IP adres.
Als ik een variable het IP adres geef en die pass krijg ik wel de juiste informatie binnen.

Het lijkt dus een issue te zijn vanuit mijn dataTransfer object. Maar wat dan exact?
Er een string van maken als in String(e.dataTransfer.getData('text')) en e.dataTransfer.getData('text').toString() werken niet - geven hetzelfde resultaat.

JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
function handleDrop(e) {
    if (e.preventDefault) {
        e.preventDefault();     // prevent default behaviour (navigating to the link)
    }

    if (e.dataTransfer) {
        var url = e.dataTransfer.getData('text');
        alert(url); // <-- Geeft correct url weer
        device.view = url; // <-- Geeft "1" door in C++ methode

        //var str = '10.10.183.93';
        //device.view = str; // <-- Werkt
    }

Acties:
  • 0 Henk 'm!

Verwijderd

Er vreemd dat een zelf gedefinieerde string wel werkt en een var die ergens uit je JS applicatie komt niet werkt.

Mischien iets met het escapen van de data of het meesturen van whitespaces ?

welk type verwacht je C++ method ?

Acties:
  • 0 Henk 'm!

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 13-09 00:05
Javascript strings zijn UTF-16; '1' is U+0031. Als je in C++ dat benadert als narrow string, op een litte-endian machine, dan is dat "1\0".

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


Acties:
  • 0 Henk 'm!

  • cenix
  • Registratie: September 2001
  • Laatst online: 16:17
@thioz: Ik geloof niet zozeer in een escaping probleem, als ik een alert() geef komt de data wel goed door. Het word righting C++ doorgegeven als QString.

@MSalters: agreed (zie mijn remark in mijn post), maar dan nog snap ik niet goed waarom het als ik een literal aan een variable toeken het werk werkt terwijl als het uit een dataTransfer object komt niet.

Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 22:43
Helaas laat je alle type-informatie weg dus het is lastig te zeggen wat er nu gebeurt. Wat zegt de documentatie van getData() over het return type? Is dat gewoon een char* of iets dergelijks? Dan moet je die eens casten naar een QChar.

Acties:
  • 0 Henk 'm!

  • cenix
  • Registratie: September 2001
  • Laatst online: 16:17
Documentatie heeft het over een DOMString. Een DOMString wordt als UTF-16 (http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-C74D1578) gebruikt.

Ook geprobeerd om de waarde als QVariant door te geven en later met toString naar een QString te vertalen. Dit geeft exact zelfde resultaat.

Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 22:43
Maar wat is het gedeclareerde return type van getData()? Als je er op een of andere manier een array van 16-bits waarden uit krijgen, zou je die mijns inziens met QString::fromUtf16() naar een Qt string moeten kunnen omzetten.

Dat QVariant niet helpt is nogal wiedes; als je daar bijvoorbeeld een char* instopt krijg je die er ook weer uit.

Acties:
  • 0 Henk 'm!

  • cenix
  • Registratie: September 2001
  • Laatst online: 16:17
Dat is mijn gedachte ook.
Echter getData is een DOM object wat in JavaScript aangeroepen wordt en retourneerd een DOMString (valuetype DOMString sequence<unsigned short>;).
Of begrijp ik je nu verkeerd :?

HTML:
1
<img src="path/to/img" data-url="10.10.183.93" />


JavaScript:
1
2
3
4
5
6
7
function handleDragStart(e) {
    e.dataTransfer.effectAllowed = 'copy';
    e.dataTransfer.setData('text', e.target.getAttribute('data-url'));
    e.dataTransfer.setDragImage(e.target, 0, 0);
    
    return true;
}

handleDrop is al eerder gegeven

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class CDevice: public QWidget
{
    Q_OBJECT

public:
    explicit CDevice(QWidget* parent = 0);
    CDevice(const CDevice& other);
    CDevice& operator=(const CDevice& other);
    ~CDevice();

    QString view() const;
    Q_INVOKABLE void setView(QString);
    Q_PROPERTY(QString view READ view WRITE setView NOTIFY viewChanged);
};
...
void CDevice::setView(QString url)
{
    if (m_strUrl != url)
    {
        m_strUrl = url;
    }


Ik kan vanuit setView dus geen fromUtf16 aanroepen daar ik al een QString te pakken heb.
Ook als ik de MIME-type als 'text/plain' of 'Text' geef, krijg ik hetzelfde (verwachte) resultaat.
Ook als ik ipv property 'view' direct setView aanroep krijg ik hetzelfde (verwachte) resultaat.

Acties:
  • 0 Henk 'm!

  • Infinitive
  • Registratie: Maart 2001
  • Laatst online: 25-09-2023
Ik ben benieuwd of het wellicht door (het ontbreken van/verkeerde) een conversie van het resultaat van getData() naar een JavaScript string komt. Je zou sowieso iets als het volgende kunnen proberen:
JavaScript:
1
device.view = "hoi" + url;

Je zou nu verwachten dat tenminste de eerste drie characters doorkomen, maar wat is de rest?

putStr $ map (x -> chr $ round $ 21/2 * x^3 - 92 * x^2 + 503/2 * x - 105) [1..4]


Acties:
  • 0 Henk 'm!

  • cenix
  • Registratie: September 2001
  • Laatst online: 16:17
Infinitive schreef op dinsdag 08 november 2011 @ 09:44:
JavaScript:
1
device.view = "hoi" + url;

Je zou nu verwachten dat tenminste de eerste drie characters doorkomen, maar wat is de rest?
Helaas, al eerder geprobeerd, resultaat is "hoi1", wat je ook zou verwachten.
In memory staat deze sequence. Je ziet dus dat er verschil zit tussen echte string en data geretourneerd via getData().

code:
1
2
3
0x144F19C2  68 00 6f 00 69 00 31 00 00 00 30 00 00 00 2e 00 00 00 31 00 00 00  h.o.i.1...0.......1...
0x144F19D8  30 00 00 00 2e 00 00 00 31 00 00 00 38 00 00 00 33 00 00 00 2e 00  0.......1...8...3.....
0x144F19EE  00 00 39 00 00 00 33 00 00 00 00 00 fd fd fd fd ab ab ab ab ab ab  ..9...3.....ýýýý««««««

[ Voor 6% gewijzigd door cenix op 08-11-2011 10:04 ]


Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Het lijkt verdacht veel op die UTF16 conversie. Een 1 gevolgd door een binaire 0; i.e., end-of-string.

Acties:
  • 0 Henk 'm!

  • cenix
  • Registratie: September 2001
  • Laatst online: 16:17
De vraag is dan hoe kun je dat of omzeilen of goed oplossen? Het lijkt me dan ook meer een probleem in de javascript/browser engine.

Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Het lijkt erop of JS je "valuetype DOMString sequence<unsigned short>;" interpreteert als een sequence van 32bit ints die elk appart naar string worden geconverteerd oid. Je ziet namelijk in je ruwe data steeds dat je 3100 wordt omgezet in 3100 0000. Dat IP staat er wel, maar als 32bits per character ipv 16.

3100 0000 -> 1
3000 0000 -> 0
2e00 0000 -> .
3100 0000 -> 1
etc.

Hijziet dus waarschijnlijk je UTF16 string als ASCII, en converteert elk van die naar UTF16. Dus 31 -> 0031, en die 00 van (0031) gaat naar 0000.

Dus:

var url = e.dataTransfer.getData('text');

is een ruwe array van bytes ipv een UTF16 string. getData returned dus byte data en snapt niet dat het eigenlijk een UTF16 string is. Die byte data wordt dan weer char voor char naar UTF16 omgezet.

Ofzoiets, ik zie even niet waar het precies fout gaat. Maar mijn verklaring is dus dat een UTF16 string wordt opgevat als ASCII/bytes en opnieuw wordt omgezet naar UTF16.

(handig trouwens dat weak-typing en automagische conversies... maakt het allemaal zo veel makkelijker ;) )

[ Voor 48% gewijzigd door Zoijar op 08-11-2011 11:50 ]


Acties:
  • 0 Henk 'm!

  • cenix
  • Registratie: September 2001
  • Laatst online: 16:17
Volgens mij is het bug in Qt's drag and drop mechanisme of QWebView (webkit component) - ik begrijp dat het Qt DnD mechanisme gebruikt wordt als DnD backend. (Dit hint ook naar Zoijar's post).
Als ik het volgende probeer wordt het element ook niet gevonden - terwijl het dat element is dat ik DnD.
Ik probeer hier het element id mee te geven zodat ik mijn url data niet in het DnD object hoef mee te geven maar aan het gedragde object opvraag.

JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
function handleDragStart(e) {
    e.dataTransfer.effectAllowed = 'copy';
    e.dataTransfer.setData('id', e.target.getAttribute('id'));
    e.dataTransfer.setDragImage(e.target, 0, 0);
    //device.view = e.target.getAttribute('data-url'); // Deze werkt!
    return true;
}

function handleDrop(e) {
    if (e.preventDefault) {
        e.preventDefault();     // prevent default behaviour (navigating to the link)
    }

    if (e.dataTransfer) {
            var id = e.dataTransfer.getData('id');
            var element = document.getElementById(id);
            if (element) {
        device.view = element.getAttribute('data-url');
            } else {
        alert('no element with id ' + id); // Deze vuurt
            }
    }
    
    if (e.stopPropagation) {
        e.stopPropagation();    // stops browser from redirecting
    }
    
    return false;
}   


Ook als ik probeer mijn drop target te voorzien van een dropzone met "move s:text/plain" krijg ik geen verbetering.

Op Linux krijg ik eenzelfde soort gedrag (daar worden alleen niet printbare karakters getoond, i.e. 1[]0[].[]1[]...). Ik denk dat ik maar eens ga kijken of ik een bug report kan indienen.
Pagina: 1