Qt 4.8 Why my QIODevice not output a text in this code? - qt

If used QTextStream console(stdout) - all work just fine, but if I wrote custom IODevice, after qInstallMsgHandler() no text in console
main.cpp
#include "remoteconsole.h"
#include <QCoreApplication>
#include <QDateTime>
#include <QTimer>
QTextStream *out;
void logOutput(QtMsgType type, const char *msg)
{
QString debugdate = QDateTime::currentDateTime().toString("yyyy.MM.dd hh:mm:ss.zzz");
*out << debugdate << " " << type << msg << endl;
}
int main(int argc, char *argv[])
{
int i;
QCoreApplication a(argc, argv);
RemoteConsole * remote = new RemoteConsole(&a);
QTextStream console((QIODevice *)remote);
out = &console;
qDebug() << "start qInstallMsgHandler";
qInstallMsgHandler(logOutput);
qDebug() << "end qInstallMsgHandler"<<endl;
for(i=0;i<10;i++){
qDebug() << i<<endl;
}
QTimer *timer = new QTimer();
a.connect(timer, SIGNAL(timeout()), &a, SLOT(quit()));
timer->start(5000);
a.exec();
return 0;
}
my IODevice implementation in file remoteconsole.h .cpp
#ifndef REMOTECONSOLE_H
#define REMOTECONSOLE_H
#include <QIODevice>
#include <QDebug>
class RemoteConsole: public QIODevice
{
Q_OBJECT
public:
RemoteConsole(QObject *parent);
~RemoteConsole();
private:
Q_DISABLE_COPY(RemoteConsole)
protected:
qint64 readData(char* data, qint64 maxSize);
qint64 writeData(const char* data, qint64 maxSize);
};
#endif // REMOTECONSOLE_H
#include "remoteconsole.h"
RemoteConsole::RemoteConsole(QObject* parent=0) :
QIODevice(parent)
{
}
RemoteConsole::~RemoteConsole(){}
qint64 RemoteConsole::readData(char *data, qint64 maxlen){
qDebug() << data <<endl;
return maxlen;
}
qint64 RemoteConsole::writeData(const char *data, qint64 len){
printf("writeData");
qDebug() << data <<endl;
return len;
}
In future I want to expand this code with QTCPServer, that send debug outputs to client connected to the device by telnet or nc.

You don't get any text in console after qInstallMsgHandler call because you send all debug data into your RemoteConsole object.
Also you've got some other problems in your code.
You should call QIODevice::open before you can operate on that device.
In the RemoteConsole::writeData function you will have an infinite loop because you use qDebug() there. qDebug() will call logOutput which will call RemoteConsole::writeData again.

Related

udp binded/connected but not datagram received

I am new to Qt, c++, recently I am trying to use UDP to receive data on my raspberrypi1 from another raspberrypi2 (multicast). I am able to bind both of them but I can't receive the data (nopendingdatagram). I wonder what I did wrong here. (As you might notice, the code below was taken from examples found online). Thank you in advanced for helping me.
// myudp.h
#ifndef MYUDP_H
#define MYUDP_H
#include <QObject>
#include <QUdpSocket>
class MyUDP : public QObject
{
Q_OBJECT
public:
explicit MyUDP(QObject *parent = 0);
//void HelloUDP();
signals:
public slots:
void readyRead();
private:
QUdpSocket *socket;
};
#endif // MYUDP_H
// myudp.cpp
#include "myudp.h"
MyUDP::MyUDP(QObject *parent) :
QObject(parent)
{
// create a QUDP socket
socket = new QUdpSocket(this);
bool result = socket->bind(QHostAddress("224.224.0.2"), 10002);
if(result)
{
qDebug() << "Socket Connected";
}
else
{
qDebug() << "Socket Not Connected";
}
connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()));
}
void MyUDP::readyRead()
{
// when data comes in
bool data_pending = socket->hasPendingDatagrams();
qDebug() << data_pending;
if(data_pending)
{
QByteArray buffer;
buffer.resize(socket->pendingDatagramSize());
QHostAddress sender;
quint16 senderPort;
socket->readDatagram(buffer.data(), buffer.size(),
&sender, &senderPort);
qDebug() << "Message from: " << sender.toString();
qDebug() << "Message port: " << senderPort;
qDebug() << "Message: " << buffer;
}
else
{
qDebug() << "No data";
}
}
#include <QCoreApplication>
#include "myudp.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MyUDP client;
client.readyRead();
return a.exec();
}
The result is as follows:
Socket Connected
false
No data

QVariant with custom class pointer does not return same address

I need to assign a pointer to a custom class in qml using QQmlContext::setContextProperty(). Another qml object has Q_PROPERTY of the same type to retrieve it again.
A simple test showed me that the conversion does not work like i thought.
#include <QCoreApplication>
#include <QDebug>
#include <QMetaType>
class TestClass
{
public: TestClass() { qDebug() << "TestClass()::TestClass()"; }
};
Q_DECLARE_METATYPE(TestClass*)
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
qDebug() << "metaTypeId =" << qMetaTypeId<TestClass*>();
auto testObject = new TestClass;
QVariant variant(qMetaTypeId<TestClass*>(), testObject);
auto test = variant.value<TestClass*>();
qDebug() << testObject << variant << test;
return 0;
}
This tiny test application gives me an output like this:
metaTypeId = 1024
TestClass::TestClass()
0x1b801e0 QVariant(TestClass*, ) 0x0
I would really like to get the same pointer out again after converting it down to a QVariant. Later I will assign it to a qml context and then the conversation must work correctly.
This works for me using Qt 5.9:
#include <QVariant>
#include <QDebug>
class CustomClass
{
public:
CustomClass()
{
}
};
Q_DECLARE_METATYPE(CustomClass*)
class OtherClass
{
public:
OtherClass()
{
}
};
Q_DECLARE_METATYPE(OtherClass*)
int main()
{
CustomClass *c = new CustomClass;
OtherClass *o = new OtherClass;
QVariant v;
v.setValue(c);
QVariant v2;
v2.setValue(o);
qDebug() << v.userType() << qMetaTypeId<CustomClass*>() << v2.userType() << qMetaTypeId<OtherClass*>();
qDebug() << v.value<CustomClass*>() << c << v2.value<OtherClass*>() << o;
return 0;
}
And the output i got:
1024 1024 1025 1025
0x81fca50 0x81fca50 0x81fca60 0x81fca60
As #thuga mentioned in the comments, you need to use void* and static_cast along with QVariant::fromValue.
#include <QCoreApplication>
#include <QDebug>
#include <QMetaType>
class TestClass
{
public: TestClass() { qDebug() << "TestClass()::TestClass()"; }
};
Q_DECLARE_METATYPE(TestClass*)
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
qDebug() << "metaTypeId =" << qMetaTypeId<TestClass*>();
auto testObject = new TestClass;
QVariant variant(QVariant::fromValue(static_cast<void*>(testObject)));
auto test = static_cast<TestClass*>(variant.value<void*>());
qDebug() << testObject << variant << test;
return 0;
}

How can I use Qt to encrypt/decrypte/play a video?

I am looking for a way to encrypt an video file and then use decrypt it to ram and play it directly.
setMedia takes a QIOdevice as second argument:
#include <QMediaPlayer>
#include <QApplication>
#include <QFile>
int main(int argc, char ** argv)
{
QApplication app(argc,argv);
QString fileName = app.arguments().at(1);
QFile io(fileName);
io.open(QFile::ReadOnly);
QMediaPlayer player;
player.setMedia(QUrl("test.mp3"), &io);
player.play();
return app.exec();
}
but just in case you really mean QDataStream:
QDataStream is buffered io, QIODevice is direct io, they're not compatible, so you have to double buffer like this:
#include <QMediaPlayer>
#include <QApplication>
#include <QFile>
#include <QBuffer>
#include <QDataStream>
int main(int argc, char ** argv)
{
QApplication app(argc,argv);
QString fileName = app.arguments().at(1);
// our double buffer
QByteArray bufferSpace;
// our stream on which we can put "media" data
QDataStream stream(&bufferSpace, QIODevice::WriteOnly);
// this is just demo data
QFile io(fileName);
io.open(QFile::ReadOnly);
stream << io.readAll();
// open an IO Device on our buffer
QBuffer buffer(&bufferSpace);
buffer.open(QBuffer::ReadOnly);
// give the IO to the media player
QMediaPlayer player;
player.setMedia(QUrl("test.mp3"), &buffer);
player.play();
return app.exec();
}
edit
here's a faster version of that "crypto" code you posted without using a buffer for the entire file:
#include <QMediaPlayer>
#include <QApplication>
#include <QFile>
#include <QBuffer>
#include <QDataStream>
static const unsigned char key = 0xAB;
class MyFunnyCrypto : public QFile /*or subclass any other IO*/
{
protected:
virtual qint64 readData(char *data, qint64 maxSize)
{
qint64 r = QFile::readData(data, maxSize);
if (r > 0) {
for (qint64 i = 0; i < r; i++) {
data[i] = data[i]^key;
}
}
return r;
}
};
int main(int argc, char ** argv)
{
QApplication app(argc,argv);
QString fileName = app.arguments().at(1);
MyFunnyCrypto io;
io.setFileName(fileName);
io.open(QFile::ReadOnly);
// give the IO to the media player
QMediaPlayer player;
player.setMedia(QUrl("test.mp3"), &io);
player.play();
return app.exec();
}
Thanks to #aep .
It doesn't have anything to do with QDataStream, and it's quite simple.
Encryption:
unsigned char key = 0xAB;
QFile file("test.mp3");
file.open(QIODevice::ReadOnly);
QByteArray byteArray = file.readAll();
for(int i=1024;i<byteArray.length();i++){
byteArray[i] = byteArray[i]^key;
}
file.close();
QFile encrypted("encrypted.mp3");
encrypted.open(QIODevice::WriteOnly);
encrypted.write(byteArray);
encrypted.close();
And decryption:
unsigned char key = 0xAB;
QFile file("encrypted.mp3");
file.open(QIODevice::ReadOnly);
auto byteArray = file.readAll();
for(int i=1024;i<byteArray.length();i++){
byteArray[i] = byteArray[i]^key;
}
QBuffer buffer(&byteArray);
buffer.open(QBuffer::ReadOnly);
// give the IO to the media player
QMediaPlayer player;
player.setMedia(QUrl(), &buffer);
player.play();
In the for-loop, I want to declare i as qint64 rather than int. But the compiler shows QByteArray::​operator[](int i).

Qt QNetworkAccessManager & simple web service return

I have a simple web service with the following URL:
http://localhost:8080/WebSvc1/webresources/generic/data?ctype=Ping
This returns a simple XML data:
<CALL TYPE='Ping'><IP>10.0.0.10</IP></CALL>
I'm trying to write a Qt program to call this web service.
The code that makes the call is below:
QUrl qrl("http://localhost:8080/WebSvc1/webresources/generic/data?ctype=Ping");
manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*)));
printf ("Calling url: [%s]\n", qPrintable(url));
QNetworkReply *reply = 0;
reply = manager->get(QNetworkRequest(qrl));
qDebug() << reply->readAll();
I'm expecting/hoping the readAll will get the XML text data and print it (via qDebug).
Instead I see nothing and the program just hangs.
UPpdate, also have this:
void obj::replyFinished(QNetworkReply *reply)
{
qDebug() << reply->readAll();
}
I've included an example (forcing a synchronous request <-> reply exchange to easy the debugging process) that should work for you:
QUrl qrl("http://localhost:8080/WebSvc1/webresources/generic/data?ctype=Ping");
qDebug() << "Calling url: " << qrl.toString();
manager = new QNetworkAccessManager();
QNetworkReply* reply = manager->get(QNetworkRequest(qrl));
QEventLoop eventLoop;
connect(reply, SIGNAL(finished()), &eventLoop, SLOT(quit()));
eventLoop.exec();
if (reply->error() != QNetworkReply::NoError)
{
qDebug() << "Network error: " << reply->error();
}
else
{
qDebug() << reply->readAll();
}
Notice that the "emitter" of the finished signal is not the QNetworkAccessManager but the reply itself.
I think your error could be with your web service. I tried your code out (slightly modified) with httpbin.org, and was getting proper replies. Maybe take a look at your code with httpbin.org and then see if you can track down what's wrong with your service.
MainWindow.cpp
#include "MainWindow.hpp"
#include <QUrl>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QNetworkAccessManager>
#include <QDebug>
MainWindow::MainWindow(QWidget* parent)
: QMainWindow(parent), manager(this) {
load();
}
void MainWindow::load() {
const QUrl url(QStringLiteral("http://httpbin.org/xml"));
QNetworkReply* reply = manager.get(QNetworkRequest(url));
connect(reply, &QNetworkReply::finished, this, [this, reply]() {
replyFinished(reply);
});
qDebug() << reply->readAll(); // The reply won't be ready by now, so
// testing here isn't very helpful.
}
void MainWindow::replyFinished(QNetworkReply* reply) {
qDebug() << reply->readAll();
reply->deleteLater();
}
MainWindow.hpp
#ifndef MAINWINDOW_HPP
#define MAINWINDOW_HPP
#include <QMainWindow>
#include <QNetworkAccessManager>
#include <QNetworkReply>
class MainWindow : public QMainWindow {
Q_OBJECT
public:
explicit MainWindow(QWidget* parent = nullptr);
public slots:
void load();
void replyFinished(QNetworkReply* reply);
private:
QNetworkAccessManager manager;
};
#endif // MAINWINDOW_HPP
main.cpp
#include "MainWindow.hpp"
#include <QApplication>
int main(int argc, char* argv[]) {
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
network.pro
QT += core gui widgets network
TARGET = network
TEMPLATE = app
DEFINES += QT_DEPRECATED_WARNINGS
CONFIG += c++11
SOURCES += \
main.cpp \
MainWindow.cpp
HEADERS += MainWindow.hpp

QT QString from QDataStream

I'm working with a buffer and I'm trying to get a string from it, but isnt working...
Example:
*void myFunc(QDataStream& in)
{
quint8 v;
in >> v;
// Ok, I caught v value successfuly
QString s;
in >> s;
// Didnt work :<
}*
The string lenght is stored on 2 first bytes...
Thanks
If the string was not written as a QString, you need to read its length and content separately.
quint8 v;
in >> v;
quint16 length = 0;
in >> length;
// the string is probably utf8 or latin
QByteArray buffer(length, Qt::Uninitialized);
in.readRawData(buffer.data(), length);
QString string(buffer);
You might have to change the endianness of the QDataStream with QDataStream::setByteOrder before reading the 16-bit length.
We should really see the writing code and how you create the QDataStream. I tried with the following sample, and in this case your function works very well:
#include <QCoreApplication>
#include <QDebug>
#include <QDataStream>
#include <QBuffer>
void myFunc(QDataStream& in)
{
quint8 v;
in >> v;
qDebug() << v;
// Ok, I caught v value successfuly
QString s;
in >> s;
qDebug() << s;
// Didnt work :<
}
int main(int argc, char ** argv) {
QCoreApplication a(argc, argv);
QBuffer buffer;
buffer.open(QBuffer::ReadWrite);
// write test data into the buffer
QDataStream out(&buffer);
quint8 ival = 42;
QString sval = "Qt";
out << ival;
out << sval;
// read back data
buffer.seek(0);
myFunc(out);
return a.exec();
}
Output when executed:
$ ./App
42
"Qt"

Resources