I have a Qt 4.7.4 app working. I am trying to update to Qt 4.8.6 however version 4.8.6 doesn't handle embedded double quotes like 4.7.4 has.
As an example the following string is one of twelve that we use as arguments to the QApplication:
QString myData =
QString("{\"type\":\"IndexFlt\",\"media\":\"1\",\"entityid\":\"0:0:0\"}");
In version 4.7.4 the twelve strings passed to QApplication as part of argv.
When I get the arguments back via theApp.arguments() in version 4.7.4 I get back all arguments with no change in formatting.
However when I pass the same argumetns to version 4.8.6 and then call theApp.arguments() the QStringList has only six entries instead of twelve.
When I look at the 6th string I see that QT took arguments 7-12 and added them to first six.
What I see in the debugger for the QStringList of arguments is different between 4.7.4 and 4.8.6. in 4.7.4
I see argument 6 as:
"{"type":"IndexFlt","media":"1","entityid":"0:0:0"}"
But with version 4.8.6 I see argument 6 as:
"{\type":"IndexFlt","media":"1","entityid":"0:0:0"} --ScriptArg:...
As you can see instead of a double quote infront of the string type I get a / and the closing } does not get a " after it got arguments 7-12 added to argument 6.
Any ideas on how to fix this? The only thing that changed in the application is the version of Qt.
You can use the following code to see the issue with embedded double quotes. Just make sure that you use at least two arguments with the first argument containing embedded double quotes. So as an example if the code below was compiled to an exe called test.exe then you would envoke test.exe this way: test.exe --DoubleQuotes="true" -NoDoubleQuotes=false
#include <QtGui/QApplication>
#include <QtCore/QStringList>
#include <iostream>
int main(int argc, char** argv)
{
for (int i=0; i < argc ; i++)
{
std::string tmp = argv[i];
std::cout << tmp << std::endl;
}
QApplication theApp(argc, argv);
QStringList vArgs = theApp.arguments();
foreach (QString t, vArgs)
{
std::cout << t.toStdString() << std::endl;
}
}
The problem you are running into stems from a bug in the argv parsing that Qt 4.8.6 implments in the template function qWinCmdLine<>() (from qcorecmdlineargs_p.h).
In Qt 4.7.4, the section of code in that function that handles escaped quotes on the command line looks like (the comments in the left column are my annotations):
if (*p == '\\') { // escape char?
/* skip escape */ p++;
if (*p == Char('\"') || *p == Char('\''))
/* keep quote */ ; // yes
else
/* else undo */ p--; // treat \ literally
} else {
if (!quote && (*p == Char('\"') || *p == Char('\''))) { // " or ' quote
/* note and */ quote = *p++;
/* skip quote */ continue;
} else if (QChar((short)(*p)).isSpace() && !quote)
break;
}
In Qt 4.8.6 that section of the function looks like:
if (*p == '\\') { // escape char?
/* BUG */ if (*(p+1) == quote)
p++;
} else {
if (!quote && (*p == Char('\"') || *p == Char('\''))) { // " or ' quote
quote = *p++;
continue;
} else if (QChar((short)(*p)).isSpace() && !quote)
break;
The snippets are very similar, except that the 4.8.6 code tries to be a little more clever by skipping the escape character if it sees the next character is a quote instead of 4.7.4's technique of skipping the escape char then undoing that action if it notices the next character isn't a '\"' or '\'. The problem is that at the line I've annotated as /* BUG */, the variable quote is only set if you're already inside a quoted section. It doesn't correctly handle an escaped quotation character that isn't in a quoted part of the command line.
Note that sometime between Qt 4.8.6 and Qt 5.3.1, the qWinCmdLine<>() function is no longer used on desktop Windows targets (it's only used on WinCE targets). Instead the Win32 API CommandLineToArgvW() is used to parse the command line into an argv array - and it looks like that brings back the behavior you are looking for (it looks like the bug is fixed in the WinCE-only version of qWinCmdLine<>(), too).
So to fix your problem you'll need to use a version of Qt other than 4.8.6 (I'm not sure at what versions the bug crept in or exactly when it was fixed), or you can patch the qcorecmdlineargs_p.h file and rebuild Qt if you need 4.8.6 for some reason.
Also note that on Windows, QCoreApplication (and therefore QApplication) ignores the argc and argv arguments you pass in. The command line that is parsed is always obtained from the Win32 API GetCommandLine(). While this behavior is documented, it wasn't what I expected and was kind of irritating when I was trying to test things by passing different argc/argv values to QCoreApplication to no effect.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With