How do I find out which suffix user has chosen when using a QFileDialog? - qt

Well I'm using the following code to get the filename for a file that needs to be stored ..
QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"),"/home/user/MyDocs/",tr("JPG files (*.jpg);;BMP files (*.bmp);;PNG files (*.png)"));
I'm providing the user with a number of options regarding the file format in which the file is to be saved. However, the returned QString only gives me the prefix filename the user have chosen, not the suffix and thus I don't know which file format the user chose. How can I detect such a file format?

The code in the question works in Windows (Qt 4.6.2 and Win XP). fileName contains the selected extension. But you are obviously using something else Windows, so you could try this workaround:
QFileDialog dialog(this, tr("Save as ..."), "/home/user/MyDocs/");
dialog.setAcceptMode(QFileDialog::AcceptSave);
QStringList filters;
filters << "JPG files (*.jpg)" << "BMP files (*.bmp)" << "PNG files (*.png)";
dialog.setNameFilters(filters);
if (dialog.exec() == QDialog::Accepted)
{
QString selectedFilter = dialog.selectedNameFilter();
QString fileName = dialog.selectedFiles()[0];
}
That is a slighty modified code from here.

You need to use the 5th optional string
I usually do it like this:
#define JPEG_FILES "JPG files (*.jpg)"
#define BMP_FILES "BMP files (*.bmp)"
#define PNG_FILES "PNG files (*.png)"
QString selectedFilter;
QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"),
"/home/user/MyDocs/",
JPEG_FILES ";;" BMP_FILES ";;" PNG_FILES, &selectedFilter);
if (fileName.isNull())
return;
if (selectedFilter == JPEG_FILES) {
...
} else if (selectedFilter == BMP_FILES) {
...
} else if (selectedFilter == PNG_FILES) {
...
} else {
// something strange happened
}
The compiler takes care to concatenate the literal strings in the argument.
I'm not sure how the returned string interacts with tr(). You'll have to test and find out. probably need to un-translate it.
It could have been nicer if the function would return the index of the selected filter but alas, it does not.
A nicer solution would be to put the filters in a list, create a string from it and then compare to the returned selected filter string to the ones in the list. This would also solve the tr() problem.

Have a look to this discussion. It uses QFileInfo on the string that was entered in a QFileDialog.

Related

Encoding a QString in JSON

I'm trying to encode a QString into a JSON string, so that I can inject it safely via QWebFrame::evaluateJavaScript(QString("o.text = %1;").arg(???)).
For example, in php using the function json_encode
echo json_encode('HELLO "me"');
The output would be
"HELLO \"me\""
This is the internal representation of the string, within the Json object.
In the same way, using Qt, how can I retrieve the internal representation of a string, as it would be encoded as a value, within a Json formatted string?
It's really not that difficult. Start by building up the structure with QJsonObjects
QJsonObject obj;
obj.insert("tag1", QString("Some text"));
Then use QDocument to get a string in Json format
QJsonDocument doc(obj);
QByteArray data = doc.toJson(QJsonDocument::Compact);
QString jsonString(data);
This will produce a string, in the form of: -
{ "tag1" : "Some Text" }
Separate items into a list, splitting on ':'
QStringList items = jsonString.split(':', QString::SkipEmptyParts);
There should be 2 items in the list, the second being the value section of the Json string
"Some Test"}
Remove the final '}'
QString value = items[1].remove('}');
Of-course, you will need to do error checking and be aware that if you have a ':' or '}' in the original string, then you'll need to check for them first.
Original answer doesn't handle : and } inside of string correctly. A similar approach using array which requires only stripping []:
QString encodeJsonStringLiteral(const QString &value)
{
return QString(
QJsonDocument(
QJsonArray() << value
).toJson(QJsonDocument::Compact)
).mid(1).chopped(1);
}
ab"c'd becomes "ab\"c'd"
Or, if you don't need double quotes around the string, replace with .mid(2).chopped(2)

trouble passing parameters to console application

I have trouble with correctly launching cloc 1.62 from windows command line using qprocess. Here is what i have:
A QStringList with all the languages cloc recognizes;
QStringList languages;
languages<<"\"ABAP\""<<"\"ActionScript\""<<"\"Ada\""<<"\"ADSO/IDSM\""<<"\"AMPLE\""<<"\"Ant\""<<"\"Apex Trigger\"";
Then i create a qstring consisting of all of the list's elements separated by comma, exept for one, which is stored in a lang variable;
QString langsinuse;
for (int i=0;i<languages.length();i++)
{
if (languages.at(i) != lang)
{
if (langsinuse.isEmpty())
{
langsinuse=langsinuse+languages.at(i);
}
else
{
langsinuse=langsinuse+','+languages.at(i);
}
}
}
then i build an arguments stringlist and launch the process:
QStringList arguments;
QProcess cloc;
QString params="cloc-1.62.exe --xml --by-file --report-file="+
list1.at(1).trimmed()+'/'+name+'/'+"report.xml"+" --exclude-lang="+langsinuse+" "+distr;
arguments<<"/k"<<params;
cloc.startDetached("cmd.exe",arguments,"cloc/");
But somehow the spaces in the languages names are not considered escaped and every word separated by space considered a different parameter for cloc, even though both words are in double quotes (for example "\"Apex Trigger\"") and clock produces a bunch of errors.
(50 errors:
Unable to read: Trigger","Arduino
Unable to read: Sketch","ASP","ASP.Net","Assembly","AutoHotkey","awk","Bourne)
It's the error that happens when you don't put a language's name that contains spaces in double quotes, int the --exclude-lang= option (for example --exclude-lang=Apex Trigger will cause an error, --exclude-lang="Apex Trigger" won't)
However if i just save the whole command i build in qt and save it in some batch file it runs just fine.
Am i missing something in escaping the double quotes correctly?
Ok i just had to pass arguments separately and not as a single string.
arguments<<"/k"<<"cloc-1.62.exe" <<"--xml"<<"--by-file"<<"--report-file="+
list1.at(1).trimmed()+'/'+name+'/'+"report.xml"<<"--exclude-lang="+langsinuse<<distr;

Qt qsettings save value in quotes

I try to save some values in ini file, it's ok while i save only one value, like:
AAA=BBB
but i found a problem, when i try to save several values like this:
AAA=BBB;CCC
it's ok, if i want to save, but if i want to read this value, i will get only BBB. I found solution of this problem, if value was saved in quotes it will be read normally:
AAA="BBB;CCC"
but, i don't know how to save value in quotes. I use following code, to save values:
configs.setValue("Settings/name", value);
I tried to save with ASCII symbol and with "\"", but it's not work. Save code:
if (!Ui->commonIncludesLineEdit->text().isEmpty()) {
value = Ui->commonIncludesLineEdit->text();
configs.setValue("Settings/CommonIncludes", value);
} else {
if (configs.contains("Settings/CommonIncludes"))
configs.remove("Settings/CommonIncludes");
}
read code:
if (configs.contains("Settings/CommonIncludes"))
Ui->commonIncludesLineEdit->setText(configs.value(
"Settings/CommonIncludes",
"Open problems").toString());
ini file:
[Settings]
CommonIncludes="C:/dev/ObfOr/Workset_latest;C:/dev/ObfOr/Workset_latest/Demo"

Qt, QUrl, QUrlQuery: Encoding special character in a query string

I create a URL query like this:
QString normalize(QString text)
{
text.replace("%", "%25");
text.replace("#", "%40");
text.replace("‘", "%27");
text.replace("&", "%26");
text.replace("“", "%22");
text.replace("’", "%27");
text.replace(",", "%2C");
text.replace(" ", "%20");
return text;
}
QString key = "usermail";
QString value = "aemail#gmail.com";
QUrlQuery qurlqr;
qurlqr.addQueryItem(normalize(key), normalize(value));
QString result = qurlqr.toString();
The result that's be expecting is :
usermail=aemail%40gmail.com.
But I received:
usermail=aemail#gmail.com
I don't know why. Can you help me?
(I'm using Qt5 on Win7)
QUrlQuery's toString by default decodes the percent encoding. If you want the encoded version try:
qurlqr.toString(QUrl::FullyEncoded)
Also you don't need to manually encode the string by replacing characters; you could instead use QUrl::toEncoded() (I suggest you read the QUrlQuery documentation).

Why a directory string loss '/' will return the parent qdir in Qt

It maybe a bug. Please read webclectic answer.
If QFileInfo(filename) loss '/', QDir::absolutePath will return the parent string. Like below code.
QFileInfo file("e:/QtExample/mytest/out/res/res1/");
QFileInfo file_no("e:/QtExample/mytest/out/res/res1");
QDir dirFile = file.absoluteDir();
QDir dirFile_no = file_no.absoluteDir();
QString strDirFile = dirFile.absolutePath(); //"E:/QtExample/mytest/out/res/res1
QString strDirFile_no = dirFile_no.absolutePath(); //"E:/QtExample/mytest/out/res
I found it with my QTreeView. My code will call the slot from QTreeView::clicked signals
connect(ui.m_pView,SIGNAL(clicked(QModelIndex)),this,SLOT(myClicked(QModelIndex)));
the slot will get the QModelIndex, then I use QFileSystemMode::fileInfo get the QFileInfo.
QFileInfo rFileInfo = m_model.fileInfo(index);
QDir absDir = rFileInfoDir.absoluteDir();
But the return of QFileInfo always return "e:/QtExample/mytest/out/res/res", so If I call QFileInfo::absoluteDir get the directory, the directory is the parent of "res1".So I will get wrong entrylst from my hope directory.
Should I add the '/' after the absoluteFilePath() to get the right QDir?
And why strDirPath equal "E:/QtExample/mytest/out/res/res1", but rDir will list the "res" directory entrylist?
//rFileInfoDir == E:/QtExample/mytest/out/res/res1
QString strDirPath = rFileInfoDir.absoluteFilePath();
QDir rDir = rFileInfoDir.absoluteDir();
If you go deep into the absoluteDir() function call you will see why this happens. In Windows the fileName function in qfsfileengine_win.cpp is called. In this function there is this code part:
if (file == AbsolutePathName) {
int slash = ret.lastIndexOf(QLatin1Char('/'));
if (slash < 0)
return ret;
else if (ret.at(0) != QLatin1Char('/') && slash == 2)
return ret.left(3); // include the slash
else
return ret.left(slash > 0 ? slash : 1);
}
You can see that it returns the part of the string left of the last separator. I don't know if this is the desired behavior or a bug. Maybe you could issue a Qt bug for this. The documentation is not clear on this matter.
From the QFileInfo::absoluteDir() docs:
Returns the file's absolute path as a QDir object.
In the case of "/foo/bar", the file is "bar" and its directory is /foo. It doesn't matter if bar is a directory or a plain file, as directories are also files. If you want something like "for files, return the parent directory, for directories, return the directory itself", you'll have to write your own little function testing via QFileInfo::isDir for what to return.
e:/QtExample/mytest/out/res/res1/res is the path to a directory called "res", e:/QtExample/mytest/out/res/res1/ is the path to an empty directory (called ""). So whether you should add a slash or not depends on what you are trying to do.
In my own personal opinion it's better not to add a final slash because it's easy to add it if you need to, while removing it is not as straightforward.

Resources