Strange behavior with QString - qt

Here's my code:
#include <QCoreApplication>
#include <QTextStream>
#include <iostream>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QTextStream out(stdout);
QString filename = "F:/temp/йцук.tx";
out << filename << endl;
const wchar_t* fn_wch = filename.toStdWString().c_str();
std::wcout << filename.toStdWString().c_str() << std::endl; //1
std::wcout << fn_wch << std::endl; //2
return a.exec();
}
The problem is rows "1" and "2" outputs different strings. But aren't they should be the same? Because I assigned fn_wch to filename.toStdWString().c_str() before that.
UPD0:
I've changed the code to prevent accessing to data of the destroyed wstring:
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QTextStream out(stdout);
QString filename = "F:/temp/йцук.tx";
out << filename << endl;
auto wstr = filename.toStdWString();
auto wchar = wstr.c_str();
std::wcout << wchar << std::endl; //1
std::wcout << wchar << std::endl; //2
std::wcout << wstr; //3
return a.exec();
}
But problem remains the same: row 1 outputs data, but 2 and 3 doesn't.

int main(int argc, char *argv[])
{
setlocale(LC_ALL, "russian");
QCoreApplication a(argc, argv);
QTextStream out(stdout);
QString filename = "F:/temp/йцук.tx";
out << filename << endl;
auto wstr = filename.toStdWString();
//auto wchar = wstr.c_str();
wchar_t wchar[wstr.size()];
wcscpy(wchar, wstr.c_str());
std::wcout << wchar << std::endl; //1
std::wcout << wchar << std::endl; //2
std::wcout << wstr; //3
return a.exec();
}
It works. Pointer in c_str() is destryed, so you need to copy data.

Related

When does `QKeySequence::match()` return `QKeySequence::PartialMatch`?

What sequences partially match?
I thought 1 partially matches Ctrl+1, but it doesn't.
Taken from the source code,
QKeySequence::SequenceMatch QKeySequence::matches(const QKeySequence &seq) const {
uint userN = count(),
seqN = seq.count();
if (userN > seqN)
return NoMatch;
// If equal in length, we have a potential ExactMatch sequence,
// else we already know it can only be partial.
SequenceMatch match = (userN == seqN ? ExactMatch : PartialMatch);
for (uint i = 0; i < userN; ++i) {
QKeyCombination userKey = (*this)[i],
sequenceKey = seq[i];
if (userKey != sequenceKey)
return NoMatch;
}
return match;
}
It seems that,
The compared sequence has to be longer than the source
The compared sequence has to start with the source
So if you have,
#include "mainwindow.h"
#include <QApplication>
#include <QDebug>
#include <QKeySequence>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QKeySequence ks_1{Qt::CTRL, Qt::Key_X, Qt::Key_Y};
QKeySequence ks_2{Qt::CTRL};
QKeySequence ks_3{Qt::CTRL, Qt::Key_X};
QKeySequence ks_4{Qt::CTRL, Qt::Key_X, Qt::Key_Y};
QKeySequence ks_5{Qt::CTRL, Qt::Key_X, Qt::Key_Y, Qt::Key_Z};
qDebug() << ks_1.count() << ks_2.count() << ks_1.matches(ks_2);
qDebug() << ks_1.count() << ks_3.count() << ks_1.matches(ks_3);
qDebug() << ks_1.count() << ks_4.count() << ks_1.matches(ks_4);
qDebug() << ks_1.count() << ks_5.count() << ks_1.matches(ks_5);
return a.exec();
}
ks_4 would be an exact match, and ks_5 would be a partial match.
Note that the length is acquired using count(), which from the source is:
int QKeySequence::count() const
{
return int(std::distance(d->key, std::find(d->key, d->key + QKeySequencePrivate::MaxKeyCount, 0)));
}
So if the previous example is declared as:
QKeySequence ks_1{Qt::CTRL + Qt::Key_X + Qt::Key_Y};
QKeySequence ks_2{Qt::CTRL};
QKeySequence ks_3{Qt::CTRL + Qt::Key_X};
QKeySequence ks_4{Qt::CTRL + Qt::Key_X + Qt::Key_Y};
QKeySequence ks_5{Qt::CTRL + Qt::Key_X + Qt::Key_Y + Qt::Key_Z};
All will be no match, since count() returns 1 for all cases above.

QRemoteObjectNode::remoteObjectAdded signal does not fire

While learning how to use QtRO tech preview module, I tried a simple 3 node network ( A registry node, a source object remoting node, and a client node).
registry node main.cpp:
#include <QCoreApplication>
#include <QRemoteObjectRegistryHost>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QRemoteObjectRegistryHost host(QUrl("tcp://127.0.0.1:5557"));
return a.exec();
}
source node main.cpp:
#include <QCoreApplication>
#include <QRemoteObjectHost>
#include <QTimer>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QTimer timer;
timer.start(10000);
QRemoteObjectHost host;
if(!host.setHostUrl(QUrl("tcp://127.0.0.1:5556"))) qDebug() << "Host url " << host.lastError();
if(!host.setRegistryUrl(QUrl("tcp://127.0.0.1:5557"))) qDebug() << "Reg url " << host.lastError();
if(!host.enableRemoting(&timer, "HostTimer")) qDebug() << "Remoting error " << host.lastError();
return a.exec();
}
client node main.cpp:
#include <QCoreApplication>
#include <QRemoteObjectNode>
#include <QTimer>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QRemoteObjectNode node(QUrl("tcp://127.0.0.1:5557"));
QObject::connect(&node, &QRemoteObjectNode::remoteObjectAdded,
[](const QRemoteObjectSourceLocation& info){
qDebug() << "New source added : " << info;
});
qDebug() << "Waiting for registry ";
node.waitForRegistry(10000);
qDebug() << "Already here sources : " << node.registry()->sourceLocations();
QTimer timer;
timer.start(5000);
QObject::connect(&timer, &QTimer::timeout,
[&](){
qDebug() << "New sources list : " << node.registry()->sourceLocations();
});
return a.exec();
}
I begin by starting the registry node, then the client node and finally the source node, with this launch sequence I expect to get the remoteObjectAdded fired up, but It didn't.
Your help will be highly appreciated.
I answer my question.
I used the wrong signal source in the connect method call.
the client node will be as :
#include <QCoreApplication>
#include <QRemoteObjectNode>
#include <QTimer>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QRemoteObjectNode node(QUrl("tcp://127.0.0.1:5557"));
QObject::connect(node.registry(), &QRemoteObjectRegistry::remoteObjectAdded,
[](const QRemoteObjectSourceLocation& info){
qDebug() << "New source added : " << info;
});
qDebug() << "Waiting for registry ";
node.waitForRegistry(10000);
qDebug() << "Already here sources : " << node.registry()->sourceLocations();
QTimer timer;
timer.start(5000);
QObject::connect(&timer, &QTimer::timeout,
[&](){
qDebug() << "New sources list : " << node.registry()->sourceLocations();
});
return a.exec();
}
It is the registry who fire the signal not the node, It sound logic after all the source nodes are connected to the registry, so it fire the remoteObjectAdded signal.

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;
}

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

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.

QNetworkReply is empty

i'm trying to implement a simple downloader. but i'm stucked because my reply and its header is empty.
#include <QtGui/QGuiApplication>
#include "qtquick2applicationviewer.h"
#include <QNetworkRequest>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QtDebug>
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QtQuick2ApplicationViewer viewer;
viewer.setMainQmlFile(QStringLiteral("qml/reply/main.qml"));
viewer.showExpanded();
QUrl url("http://www.speedtest.qsc.de/10MB.qsc");
QNetworkRequest request( url );
request.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true);
QByteArray range;
range = "bytes=" + QByteArray::number( 0 ) + "-";
request.setRawHeader("Range", range );
QNetworkAccessManager accessManager;
QNetworkReply* reply = accessManager.get( request );
qDebug() << __FILE__ << ":" << __LINE__ << reply->size();
QList<QByteArray> headerFields = reply->rawHeaderList();
qDebug() << __FILE__ << ":" << __LINE__ << headerFields.count();
for( qint64 i = 0; 0 < headerFields.count(); i++ ) {
QString string( headerFields.at(i));
qDebug() << __FILE__ << ":" << __LINE__ << string;
}
return app.exec();
}
what do i have to do, so that my reply isn't empty anymore?
thanks in advance!
I used multiple QNetworkAccessManager, so that's what caused problems because I didn't know that I should only use one per app.

Resources