Config file gets overwritten in qt - qt

I am writing data to a config file using the following code.
QSettings settings("/root/configFile.ini",QSettings::IniFormat);
QString userName = lineEditUsername.text();
QString password = lineEditPassword.text();
QList<QString> listUsername;
QList<QString> listPassword;
settings.beginWriteArray("UserData");
for(i=0;i<listUsername.size();i++)
{
Qstring user = listUsername.at(i);
Qstring pass = listPassword.at(i);
settings.setArryIndex(i);
settings.setValue("Username",user);
settings.setValue("Password",pass);
}
settings.endArray();
}
Now when I run the code first time and give 4 or 5 values they are formed in proper order in the file. However if I run the application for second time the values start overwriting from first position. Can some one suggest me some solution for this?

Instead of creating and maintaining arrays and indexes, I would propose to create user credentials map and store it in the settings file as follows:
QSettings settings("/root/configFile.ini", QSettings::IniFormat);
QString userName = lineEditUsername.text();
QString password = lineEditPassword.text();
QList<QString> listUsername;
QList<QString> listPassword;
//settings.beginWriteArray("UserData");
QVariantMap userDataMapping;
for(int i = 0; i < listUsername.size() ; i++)
{
QString user = listUsername.at(i);
QString pass = listPassword.at(i);
userDataMapping[user] = pass;
//settings.setArryIndex(i);
//settings.setValue("Username",user);
//settings.setValue("Password",pass);
}
// Store the mapping.
settings.setValue("UserData", userDataMapping);
//settings.endArray();
// ...
This will store your data in ini file in the following format:
UserData=#Variant(\0\0\0\b\0\0\0\x1\0\0\0\x6\0\x64\0\x64\0\x64\0\0\0\n\0\0\0\x6\0\x62\0\x62\0\x62)
When you read settings, do something like this:
[..]
QVariant v = settings.value("UserData");
QVariantMap map = v.value<QVariantMap>();
QMapIterator<QString, QVariant> i(map);
while (i.hasNext()) {
i.next();
QString user = i.key();
QString pass = i.value().toString();
}

You need to retrieve the amount of existing entries before adding a new one. Something like this:
int size = settings.beginReadArray( "UserData" );
settings.endArray();
settings.beginWriteArray( "UserData" );
settings.setArrayIndex( size ); // Note: Maybe 'size - 1', not sure
// ...
settings.endArray();
setArrayIndex( size ) will move the array index to the end and will thus no longer override an existing entry

Related

Qt QMap<int, MyClass> ignores insert command

I've a question that couldn't find anywhere. I have a QMap that's ignoring the QMap.insert(Key, Value) command. Here's the code:
//gets the selected problem index on the ProblemList
int selProblem = ui->tree_projects->currentItem()->data(0, Qt::UserRole).toInt();
//creates a new problem, sets its values and then replaces the old one on the ProblemsList variable
ProblemSets nProblem;
if(!problemsList.isEmpty()) //problemsList is an attribute of MainWindow
nProblem = problemsList.value(selProblem);
// some data collection that has been omitted because isn't important
// temporary maps that will carry the modifications
QMap<int, QString> nResName, nResType;
//data insertion into the maps
//these are fine
nResName.insert(fIdx, results_model->data(results_model->index(fIdx, 0)).toString());
nResType.insert(fIdx, results_model->data(results_model->index(fIdx, 1)).toString());
//replaces the old maps with the new ones
nProblem.SetProbResultsNames(nResName);
nProblem.SetProbResultsTypes(nResType);
//replaces the old problem with the new one
problemsList.insert(selProblem, nProblem); //this is the line that's doing nothing
}
That last line appears to be doing nothing! I've even tried to use
problemsList.remove(selProblem);
problemList.insert(selProblem, nProblem);
but got a similar result: the map not being inserted at the index selProblem. It got inserted, but with an outdated value - the same one of the deleted index -. I've checked on Debug and all the indexes and variables are correct, but when the .insert hits, nothing happens.
The most awkward thing is that this code is a copy/paste that I made from another method that I'm using that does similar thing, just changing the variable names, but that one works.
EDIT 1: This is the contents of nProblem, selProb and problemsList.value(selProblem)
Just before the Line:
problemsList.insert(selProblem, nProblem);
selProb: 0
nProblem:
ProbResultsNames: "NewRow0"
ProbResultsType: "Real"
problemsList.value(selProblem):
ProbResultsNames: non-existent
ProbResultsType: non-existent
After the line
problemsList.insert(selProblem, nProblem);
selProb: 0
nProblem:
ProbResultsNames: "NewRow0"
ProbResultsType: "Real"
problemsList.value(selProblem):
ProbResultsNames: non-existent
ProbResultsType: non-existent
EDIT 2:
class ProblemSets
{
public:
ProblemSets();
virtual ~ProblemSets();
ProblemSets(const ProblemSets& other);
ProblemSets& operator=(const ProblemSets& other);
//I hid getters and setters to avoid pollution on the post
private:
int index;
bool usingBenchmark;
QString functionSelected;
QString info;
QMap<int, QString> probVars_name, probVars_type, probResultsNames, probResultsTypes;
QMap<int, float> probVars_min, probVars_max;
QMap<int, int> probVars_stpSize, probVars_stp;
int varsNumber; // holds how many vars has been created, just for display purposes
int resNumber; // holds how many results has been created, just for display purposes
};
A simple test proves that QMap works as expected:
QMap<int, QString> mm;
mm.insert(1, "Test1");
qDebug() << mm[1]; // "Test1"
mm.remove(1);
qDebug() << mm[1]; // "" (default constructed value)
mm.insert(1, "Test2");
qDebug() << mm[1]; // "Test2"
Which means that the problem lies in your code.
This statement itself is highly suspicious:
That last line appears to be doing nothing!
Because then you go on to say that the map still contains the "old value". But you removed that key, so if the insert() method didn't work, you shouldn't be getting the old value, but a default constructed value.
Which means that the problem is most likely that nProblem has the same value as the one that is previously associated to that key in the map. The map works, you values are likely wrong.
Found the issue! I didn't have both the variables declared on the copy method of the ProblemSets class.
Solved simply adding them to the copy method
MainWindow::ProblemSets::ProblemSets(const ProblemSets& other)
{
// copy
index = other.index;
usingBenchmark = other.usingBenchmark;
functionSelected = other.functionSelected;
info = other.info;
probVars_name = other.probVars_name;
probVars_type = other.probVars_type;
probVars_min = other.probVars_min;
probVars_max = other.probVars_max;
probVars_stpSize = other.probVars_stpSize;
probVars_stp = other.probVars_stp;
//here
probResultsNames = other.probResultsNames;
probResultsTypes = other.probResultsTypes;
//
varsNumber = other.varsNumber;
resNumber = other.resNumber;
}
I had this issue before with the std::vector class, and that's why I suspected that could be that. Thanks to everyone that helped!

How do I read a DICOM tag within another tag with ITK?

I'm using ITK to read a DICOM file, calling
dicomIO->GetValueFromTag(...)
to read a tag value. This works fine for tags like "300a|011e" (gantry angle). The problem comes trying to read tag "0018|0060" which is embedded inside "3002|0030".
If I use GetValueFromTag for "3002|0030" I read back an empty string as "3002|0030" is exposure sequence and has no value. How do I read tags within tags with ITK? Looking through the ITK documentation I can't see any way to do this?
Apparently you can't use ImageIOType to read sequences from DICOM, instead you have to use GDCM.
#include "gdcmReader.h"
#include "gdcmImage.h"
#include "gdcmDataElement.h"
#include "gdcmTag.h"
using namespace gdcm;
bool readGDCMTags(std::string filename, float &kvp)
{
Reader reader;
reader.SetFileName(filename.c_str());
reader.Read();
File &file = reader.GetFile();
DataSet &ds = file.GetDataSet();
const Tag tag(0x3002, 0x0030);
const Tag subTag(0x0018, 0x0060);
const DataElement &seq = ds.GetDataElement(tag);
SmartPointer<SequenceOfItems> sqi = seq.GetValueAsSQ();
assert(sqi->GetNumberOfItems() == 1);
Item &item = sqi->GetItem(1);
DataSet &subds = item.GetNestedDataSet();
if (!subds.FindDataElement(subTag))
{
return false;
}
const DataElement &de = item.GetDataElement(subTag);
const ByteValue *value = de.GetByteValue();
char *buffer;
VL vl = value->GetLength();
uint32_t length = (uint32_t)vl;
buffer = new char[length + 1];
value->GetBuffer(buffer, length);
buffer[length] = 0;
kvp = (float)atof(buffer);
delete buffer;
return true;
}
Usually that tag should be at the top level, as its the peak voltage used for the Xray/CT scanner. Have you tried to simply read the tag "0018|0060" directly, like:
dicomIO->GetValueFromTag("0018|0060")
?

QFile: new file name append to tho last saved

I'm looking for the error I made on this code, but I can not find any solution since hours..
This function should simpli save a file to a directory:
void MyClass::saveSettingsToFile(QString file_name)
{
QString path;
path = dir.append(file_name);
QFile my_file(path);
if (!my_file.open(QFile::WriteOnly))
{
qDebug() << "Could not open file for writing";
}
QTextStream out(& my_file);
out << "some text \n"
my_file.flush();
my_file.close();
path = "";
file_name ="";
}
Where dir is a QString containing the directory, file_name is gathered from a lineEdit field.
When I first call the function with, for example file_name = "aaaa.txt", I find this aaaa.txt in the specified directory. All right.
When then I call again the function with file_name = "bbbb.txt", I find in the specified directory this file: aaaa.txtbbbb.txt, instead of I
bbbb.txt
It seems to me a very s****d error, but I cannot find what!
EDITED: there was this mistake QTextStream out(& path); instead of QTextStream out(& my_file);
You are modifying dir variable with QString::append. Variable dir is obviously a class member of MyClass. Try this instead:
void MyClass::saveSettingsToFile(QString file_name)
{
QString path(dir);
path.append(file_name);
QFile my_file(path);
//...
}
The QString::append function modify the parameter value itself as you can see in the documentation: http://doc.qt.io/qt-5/qstring.html#append
Example:
QString x = "free";
QString y = "dom";
x.append(y);
// x == "freedom"
So, what happens is that it keeps appending the content to the dir variable, not only assigning the result to path.

Iterate through registry folders with Qt

I need to list the devices in the HID Bluetooth LE (BTHLE) folder of the HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\ directory. By using
#define REG_PATH "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Enum\\BTHLE"
QSettings settings(REG_PATH, QSettings::NativeFormat);
QStringList regReturn = settings.allKeys();
I can get to all folders and subfolders of the path, but I need to scan through the folders, find those devices with a given PID and VID and a given value of the registrykey FriendlyName to identify my device(s).
How can this be done?
In order to obtain content of a particular sub folder, you can do the following (I used another example, because I don't know the structure of the BTHLE directory):
[..]
// Get the value of HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\VID_045E&PID_00B4\5&1b6962&0&1\Class key
const QString top("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Enum\\USB");
const QString device("VID_045E&PID_00B4");
QSettings settings(top, QSettings::NativeFormat);
settings.beginGroup(device); // Limit keys by this device only.
QStringList regReturn = settings.allKeys();
QString vStr = regReturn[1]; // 5&1b6962&0&1/Class
QString v = settings.value(regReturn[1]).toString(); // returns "USB"

how to set a value for the listwidget item?

I create A list widget in which I add items...my items are the filenames. Is any way to store the filepaths of this filenames? I want to know how to set a specific value to an item in the listwidget?
You can use:
ListWidgetItem::setData(int role,Qvariant data);
to store your filePath;
like this:
QString fileName = "hello.txt";
QString filePath = "/home/user/hello.txt";
//Adding to listWidget
QListWidgetItem *item =new QListWidgetItem();
item->setText(fileName);
item->setData(1,filePath);//here role is set as 1
listWidget->addItem(item);
//For taking back that filePath
QString filePath = listWidget->currentItem()->data(1); //note::: role equals 1

Resources