How get raw answer data in QWebEngineView? - qt

Next examples work on small html pages, but dont work if page return big html data or json
I try this after loadFinished signal
view->page()->toHtml([cc](const QString &result){
qDebug() << "result ready";
qDebug() << "result string ="<<result;
});
I see "result ready", but second string not print, also I try this:
v->page()->runJavaScript("function jsfun(){return document.getElementsByTagName('html')[0].outerHTML;};");
//v->page()->runJavaScript("alert(jsfun())"); //work correctly
v->page()->runJavaScript("jsfun();",[this](const QVariant &v) {
qDebug() << "result ready";
qDebug() << "result string ="<<v.toString();
});
but again dont see second string

All example work correctly, but if buffer very big qDebug dont print data, you can write data to file or print part of data
Example (call toHtml after loadFinished signal) :
view->page()->toHtml([cc](const QString &result){
QFile file("outerHTML.html");
if(!file.open(QFile::WriteOnly | QFile::Text)){
qDebug() << "Cannot create a file";
return;
}
QTextStream stream(&file);
stream << buff;
file.close();
}

Related

QAbstractVideoSurface generating A Null Image

I'm reimplemented the present method from a QAbstractVideo Surface in order to capture frames from an IP camera.
This is my reimplemented methods (the required ones):
QList<QVideoFrame::PixelFormat> CameraFrameGrabber::supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const
{
Q_UNUSED(handleType);
return QList<QVideoFrame::PixelFormat>()
<< QVideoFrame::Format_ARGB32
<< QVideoFrame::Format_ARGB32_Premultiplied
<< QVideoFrame::Format_RGB32
<< QVideoFrame::Format_RGB24
<< QVideoFrame::Format_RGB565
<< QVideoFrame::Format_RGB555
<< QVideoFrame::Format_ARGB8565_Premultiplied
<< QVideoFrame::Format_BGRA32
<< QVideoFrame::Format_BGRA32_Premultiplied
<< QVideoFrame::Format_BGR32
<< QVideoFrame::Format_BGR24
<< QVideoFrame::Format_BGR565
<< QVideoFrame::Format_BGR555
<< QVideoFrame::Format_BGRA5658_Premultiplied
<< QVideoFrame::Format_AYUV444
<< QVideoFrame::Format_AYUV444_Premultiplied
<< QVideoFrame::Format_YUV444
<< QVideoFrame::Format_YUV420P
<< QVideoFrame::Format_YV12
<< QVideoFrame::Format_UYVY
<< QVideoFrame::Format_YUYV
<< QVideoFrame::Format_NV12
<< QVideoFrame::Format_NV21
<< QVideoFrame::Format_IMC1
<< QVideoFrame::Format_IMC2
<< QVideoFrame::Format_IMC3
<< QVideoFrame::Format_IMC4
<< QVideoFrame::Format_Y8
<< QVideoFrame::Format_Y16
<< QVideoFrame::Format_Jpeg
<< QVideoFrame::Format_CameraRaw
<< QVideoFrame::Format_AdobeDng;
}
bool CameraFrameGrabber::present(const QVideoFrame &frame)
{
//qWarning() << "A frame";
if (frame.isValid()) {
//qWarning() << "Valid Frame";
QVideoFrame cloneFrame(frame);
cloneFrame.map(QAbstractVideoBuffer::ReadOnly);
const QImage image(cloneFrame.bits(),
cloneFrame.width(),
cloneFrame.height(),
QVideoFrame::imageFormatFromPixelFormat(cloneFrame .pixelFormat()));
qWarning() << "Is created image NULL?" << image.isNull();
if (!image.isNull())
emit nextFrameAsImage(image);
cloneFrame.unmap();
return true;
}
return false;
}
And this is is how I used it:
grabber = new CameraFrameGrabber(this);
connect(grabber,&CameraFrameGrabber::nextFrameAsImage,this,&QCmaraTest::on_newFrame);
QMediaPlayer *a = new QMediaPlayer(this);
QString url = "http://Admin:1234#10.255.255.67:8008";
a->setMedia(QUrl(url));
a->setVideoOutput(grabber);
a->play();
The problem is that the image that is created is null. As far as I can tell, this can only be because the frame is valid but does not contain data.
Any ideas what the problem could be?
Important Detail: If I set the stream to a QVideoWidget and simply show that, it works just fine.
So I found out what the problem was.
This:
QVideoFrame::imageFormatFromPixelFormat(cloneFrame .pixelFormat())
Was returning invalid format because the IP cam gave the format as a YUV format which QImage can't handle. The solution was to force the format and the only one I found that did not make the program crash was: QImage::Format_Grayscale8.
With that, it worked.

Read all input from QSerialPort

I am receiving data in this shape:
Q1\n
9.70E-6\n
OK>
from an external device via QSerialPort, but with my reading routine
QString request = "Hello";
qDebug() << "TransAction started!";
QByteArray requestData = request.toLocal8Bit();
qDebug() << "Writing data: " << requestData;
serial->write(requestData);
qDebug() << "Data written";
if(serial->waitForBytesWritten(waitTimeout))
{
if(serial->waitForReadyRead(waitTimeout))
{
qDebug() << "Waiting for data!";
QByteArray responseData = serial->readAll();
while(serial->waitForReadyRead(100))
responseData += serial->readAll();
responseData.replace('\n', ' ');
QString response(responseData);
QByteArray response_arr = response.toLocal8Bit();
qDebug() << "Response is: " << response_arr.toHex();
emit this->response(response);
}
else
{
qDebug() << "Wait read response timeout";
emit this->timeout(tr("Wait read response timeout %1").arg(QTime::currentTime().toString()));
}
}
else
{
qDebug() << "Wait write request timeout!";
emit this->timeout(tr("Wait write request timeout %1").arg(QTime::currentTime().toString()));
}
I only get
Q1
as response. How can I modify my code such that I am able to read all input data?
Update:
When testing it with the serial port script described here: https://stackoverflow.com/a/7654527/2546099, everything works. Apparently the problem is that the qt-version stops reading after the first line break. This problem consists also if I add
char buffer[1000];
for(int i = 0; i < 1000; i++)
{
int tmp = serial->read(buffer, 1000);
if(tmp > 0)
qDebug() << buffer;
}
directly after the line
qDebug() << "Waiting for data!";
Then I still only get the first line (without the \n). Changing times does not change the received data.
The answer to my problem is (partly) described in this question: External vs internal declaration of QByteArray. My problem (why I did not receive any further data) was that I did not send a \x00D after the input line, thus the device just echoed my input, and was waiting for the Enter afterwards. After the input looks exactly as the first line, I misunderstood it for just getting the first line, and nothing else.

Why is QString printed with quotation marks?

So when you use qDebug() to print a QString, quotation marks appears suddenly in the output.
int main()
{
QString str = "hello world"; //Classic
qDebug() << str; //Output: "hello world"
//Expected Ouput: hello world
}
I know we can solve this with qPrintable(const QString), but I was just wondering why does QString work like that?, and Is there a method inside QString to change the way it's printed?
Qt 5.4 has a new feature that lets you disable this. To quote the documentation:
QDebug & QDebug::​noquote()
Disables automatic insertion of quotation characters around QChar, QString and QByteArray contents and returns a reference to the
stream.
This function was introduced in Qt 5.4.
See also quote() and maybeQuote().
(Emphasis mine.)
Here's an example of how you'd use this feature:
QDebug debug = qDebug();
debug << QString("This string is quoted") << endl;
debug.noquote();
debug << QString("This string is not") << endl;
Another option is to use QTextStream with stdout. There's an example of this in the documentation:
QTextStream out(stdout);
out << "Qt rocks!" << endl;
Why?
It's because of the implementation of qDebug().
From the source code:
inline QDebug &operator<<(QChar t) { stream->ts << '\'' << t << '\''; return maybeSpace(); }
inline QDebug &operator<<(const char* t) { stream->ts << QString::fromAscii(t); return maybeSpace(); }
inline QDebug &operator<<(const QString & t) { stream->ts << '\"' << t << '\"'; return maybeSpace(); }
Therefore,
QChar a = 'H';
char b = 'H';
QString c = "Hello";
qDebug()<<a;
qDebug()<<b;
qDebug()<<c;
outputs
'H'
H
"Hello"
Comment
So why Qt do this? Since qDebug is for the purpose of debugging, the inputs of various kinds of type will become text stream output through qDebug.
For example, qDebug print boolean value into text expression true / false:
inline QDebug &operator<<(bool t) { stream->ts << (t ? "true" : "false"); return maybeSpace(); }
It outputs true or false to your terminal. Therefore, if you had a QString which store true, you need a quote mark " to specify the type.
Qt 4: If the string contains just ASCII, the following workaround helps:
qDebug() << QString("TEST").toLatin1().data();
Simply cast to const char *
qDebug() << (const char *)yourQString.toStdString().c_str();
one liner no quotes: qDebug().noquote() << QString("string");

Empty buffer when reading from a QTcpSocket

I am creating a simple threaded TCP server (based on the threaded Fortune server example). I have connected the readyRead signal to my readCommand slot, and I confirmed that the readCommand function fires after I've telnetted to my server and sent a string (followed by enter).
The function below outputs "In readCommand" once I send the string HELLO, then the output "new inBuffer" always shows empty ("").
void FortuneThread::readCommand()
{
qDebug() << "in readCommand" << endl;
QDataStream in(tcpSocketPtr);
in.setVersion(QDataStream::Qt_4_0);
in >> inBuffer;
qDebug() << "new inBuffer: " << inBuffer << endl;
...
}
If I print out tcpSocket->bytesAvailable(), then I see a growing count of characters as I send more via telnet. I'm just not getting them out of the socket...the code above is copied from the Fortune Client example so I assumed it would work. Am I using QDataStream wrong?
You should not initialize your QDataStream with QTcpSocket.
You should read the data from the socket io device with QByteArray QIODevice::readAll().
You should write the byte array of the previous operation into the data stream with the "<<" operator.
So, the code should look something like this:
void FortuneThread::readCommand()
{
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out << tcpSocketPtr->readAll();
...
}
The codes like these would work:
QByteArray res;
res.reserve(m_tcp_socket_ptr->bytesAvailable());
res = m_tcp_socket_ptr->readAll();
qDebug() << res;

QXmlQuery and XSLT20: Resultant Output String is empty everytime, works well on shell(xmlpattern)

I am writing a class to parse Itunes Libray File using QXmlQuery and QT-XSLT.
Here's my sample code:
ItunesLibParser::ItunesLibParser()
{
pathToLib = QString("/Users/rakesh/temp/itunes_xslt/itunes_music_library.xml");
}
void ItunesLibParser::createXSLFile(QFile &inFile)
{
if (inFile.exists()) {
inFile.remove();
}
inFile.open(QIODevice::WriteOnly);
QTextStream out(&inFile);
out << QString("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>");
out << QString("<xsl:stylesheet version=\"2.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">");
out << QString("<xsl:output method=\"text\" />");
out << QString("<xsl:template name=\"playlistNames\">");
out << QString("<xsl:value-of select=\"child::integer[preceding-sibling::key[1]='Playlist ID']\"/>");
out << QString("<xsl:text>
</xsl:text>");
out << QString("<xsl:value-of select=\"child::string[preceding-sibling::key[1]='Name']\"/>");
out << QString("<xsl:text>
</xsl:text>");
out << QString("</xsl:template>");
out << QString("<xsl:template match=\"/\">");
out << QString("<xsl:for-each select=\"plist/dict/array/dict\">");
out << QString("<xsl:call-template name=\"playlistNames\"/>");
out << QString("</xsl:for-each>");
out << QString("</xsl:template>");
out << QString("</xsl:stylesheet>");
inFile.close();
return;
}
void ItunesLibParser::dumpPlayList()
{
QXmlQuery query(QXmlQuery::XSLT20);
query.setFocus(QUrl(pathToLib));
QFile xslFile("plist.xsl");
createXSLFile(xslFile);
query.setQuery(QUrl("plist.xsl"));
QStringList* outDump = new QStringList();
query.evaluateTo(outDump);
if(outDump != NULL) {
QStringList::iterator iter = (*outDump).begin();
for (; iter != (*outDump).end();
++iter)
//code flow doesn't come here. It means being() == end()
std::cout << (*iter).toLocal8Bit().constData() << std::endl;
}
return;
}
OutDump here doesn't contain data. While in Shell (xmlpatterns-4.7 mystlye.xsl itunes_music_library.xml ), If I run my Query I get proper output.
Is there anything, wrong I am doing while calling it programatically? I checked out plist.xsl is created properly, but my doubt is whether "/Users/rakesh/temp/itunes_xslt/itunes_music_library.xml" this is getting loaded or not? Or there might be another reasons, I am confused. Is there any experts to throw some light onto problem, I will be glad.
Intead from reading from the file, I read the file into buffer and converted that int string as passed to setquery. That solved the problem.
Here's sample code for those who could face similar problem in future.
void ITunesMlibParser::parsePlayListItemXml(int plistId)
{
QXmlQuery xQuery(QXmlQuery::XSLT20);
QFile inFile("/Users/rakesh/temp/itunes_xslt/itunes_music_library.xml");
if (!inFile.open(QIODevice::ReadOnly)) {
return;
}
QByteArray bArray;
while (!inFile.atEnd()) {
bArray += inFile.readLine();
}
QBuffer xOriginalContent(&bArray);
xOriginalContent.open(QBuffer::ReadWrite);
xOriginalContent.reset();
if (xQuery.setFocus(&xOriginalContent))
std::cout << "File Loaded" << std::endl;
//..
//..
}
Thanks
Rakesh

Resources