How to properly use QSettings - qt

I want to use QSettings to save highscores but it doesn't work properly. I'm saving and reading those values in 2 different files.
This is my code responsible for adding values into array:
QSettings settings;
settings.beginWriteArray("results");
int size = settings.beginReadArray("results");
settings.setArrayIndex(size);
settings.setValue("result", "qwerty");
and reading:
QSettings settings;
QString tmp = "";
int size = settings.beginReadArray("results");
for(int i = 0; i < size; ++i)
{
settings.setArrayIndex(i);
tmp += settings.value("result").toString();
}
ui->label->setText(tmp);

I would do it like this:
Lets say that we have two functions member of a class to load and save the scores.
To use the registry, you have to specify the application name and editor:
QSettings settings("<MyEditorName>","<myAppName>");
saveScores(settings);
loadScores(settings);
to use a file, you have to provide the file path and format:
QSettings settings("<filepath>",QSettings::iniFormat);
saveScores(settings);
loadScores(settings);
from your code and the documentation; the member function would be as follow.
The class countains a vector of scores (QVector mScores)
Function to save the scores:
void myClass::saveScores(QSettings& iSettings)
{
iSettings.beginGroup("Scores");
iSettings.beginWriteArray("results");
for(int i=0; i<mScores.count();i++)
{
iSettings.setArrayIndex(i);
iSettings.setValue("result",mScores[i]);
}
iSettings.endArray();
iSettings.endGroup();
}
Function to load the scores
void myClass::loadScores(QSettings& iSettings)
{
iSettings.beginGroup("Scores");
int size = iSettings.beginReadArray("results");
mScores.resize(size);
for(int i=0;i<size;i++)
{
iSettings.setArrayIndex(i);
mScores[i] = iSettings->value("results").toInt();
}
iSettings.endArray();
iSettings.endGroup();
}
I am using groups to provide better visibility in the saving file but you can remove them

The beginReadArray() after beginWriteArray() is causing the problem. Do this:
QSettings settings;
int size = settings.beginReadArray("results");
settings.endArray();
settings.beginWriteArray("results");
settings.setArrayIndex(size);
settings.setValue("result", "qwerty");
settings.endArray();
Note you need to call endArray() when finished.

Using QSettings to read an ini file also showing the required format of the expected ini file\n
Format of alphabet.ini :
[A_SECTION]
AA=20
BB=40
CC=0
[B_SECTION]
DD=100
EE=270
FF=3000
Simple code to read alphabet.ini :
QSettings settings("C:\\Qt\\qtcreator-2.5.2\\testingProg\\alphabet.ini",QSettings::IniFormat);
settings.beginGroup("A_SECTION");
const QStringList AchildKeys = settings.childKeys();
QHash<QString, QString> Avalues;
foreach (const QString &childKey, AchildKeys)
{
Avalues.insert(childKey, settings.value(childKey).toString());
qDebug() << childKey << " : " <<settings.value(childKey).toString();
}
settings.endGroup();
qDebug() << ";
settings.beginGroup("B_SECTION");
const QStringList BchildKeys = settings.childKeys();
QHash<QString, QString> Bvalues;
foreach (const QString &childKey, BchildKeys)
{
Bvalues.insert(childKey, settings.value(childKey).toString());
qDebug() << childKey << " : " <<settings.value(childKey).toString();
}
settings.endGroup();
The output:
"AA" : "20"
"BB" : "40"
"CC" : "0"
"DD" : "100"
"EE" : "270"
"FF" : "3000"

Related

No viable overloaded "=" in qt

I wrote the code below, but I get a notification saying No viable overloaded "=".
(Note that the list id contains some strings)
QList<QString>id;
QList<int>::iterator iter;
iter = std::find(logid.begin(), logid.end(), id);
The issue is that you are using the std::find function incorrectly. You are also trying to find inside a list another list.
Try this:
#include <QtDebug>
QList<int> logid = {1, 2, 3};
QList<QString> ids = {"2", "5"};
for (const auto &id : ids) {
auto it = std::find_if(logid.begin(), logid.end(), [&](const int x) {
return x == id.toInt();
});
if (it != logid.end()) {
// Valid item
qDebug() << "Address" << &it;
qDebug() << "Value" << *it;
}
}
Note: since ids is a List of QString, you need to convert it to int.

QFileSystemModel and Proxy sort differently in QTreeView

I want to show only mounted drives sorted by drive letter in windows using Qt 5.10. Here is my test code:
#include <QtWidgets>
#include <QDebug>
QStringList mountedDrives;
class FSFilter : public QSortFilterProxyModel
{
public:
FSFilter(QObject *parent) : QSortFilterProxyModel(parent) {}
protected:
bool filterAcceptsRow(int row, const QModelIndex &par) const override
{
QModelIndex idx = sourceModel()->index(row, 0, par);
QString path = idx.data(QFileSystemModel::FilePathRole).toString();
QString path2 = idx.data(Qt::DisplayRole).toString();
bool mounted = mountedDrives.contains(path);
if (mounted) {
qDebug() << "QFileSystemModel::FilePathRole =" << path
<< " Qt::DisplayRole =" << path2;
return true;
}
else return false;
}
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
// get mounted drives only
foreach (const QStorageInfo &storage, QStorageInfo::mountedVolumes()) {
if (storage.isValid() && storage.isReady()) {
if (!storage.isReadOnly()) {
mountedDrives << storage.rootPath();
}
}
}
QFileSystemModel *fsModel = new QFileSystemModel;
fsModel->setRootPath("");
FSFilter *fsFilter = new FSFilter(fsModel);
fsFilter->setSourceModel(fsModel);
fsFilter->setSortRole(QFileSystemModel::FilePathRole); // now it works
fsModel->fetchMore(fsModel->index(0,0));
QTreeView tree;
tree.setModel(fsFilter); // different sort if use
tree.setModel(fsFilter);
tree.setSortingEnabled(true);
tree.sortByColumn(0, Qt::AscendingOrder);
tree.resize(800, 400);
tree.setColumnWidth(0, 300);
tree.setWindowTitle(QObject::tr("File System Test"));
tree.show();
return app.exec();
}
This works fine, producing this output, except it is not sorted by drive letter:
Running the same code, but setting the treeview model as
tree.setModel(fsModel); // use QFileSystemModel, not QSortFilterProxyModel
results in the following, where the items are sorting the way I want:
I thought this might be a role issue. Here is the output from my qDebug statements:
QFileSystemModel::FilePathRole = "C:/" Qt::DisplayRole = "C:"
QFileSystemModel::FilePathRole = "D:/" Qt::DisplayRole = "Data
(D:)"
QFileSystemModel::FilePathRole = "E:/" Qt::DisplayRole = "Photos
(E:)"
QFileSystemModel::FilePathRole = "F:/" Qt::DisplayRole =
"Archive (F:)"
QFileSystemModel::FilePathRole = "H:/" Qt::DisplayRole = "Old D
(H:)"
QFileSystemModel::FilePathRole = "I:/" Qt::DisplayRole = "Old C
(I:)"
So I included this line
fsFilter->setFilterRole(QFileSystemModel::FilePathRole);
but this did not help.
Solution (corrected in code listing above):
fsFilter->setSortRole(QFileSystemModel::FilePathRole);
You should reimplement virtual function lessThan in FSFilter, by default it sort alphabetically, but in this case you need take into account first and last letters in drive name.

Comparison in text file using Qt

I am beginner in UI design using Qt. My project now is doing comparison. For example: if I have 2 text file.
How can I compare the number line by line? Because I have so many text file like this, and I need compare them on by one.What I can do now is only read the text file by line order. Thank you so much!
The procedure is simple
Read both files (always make sure they are opened successfully)
Read files line by line and convert strings to numbers for comparison.
Quit if there is no data left.
Moreover, you need to make sure that the format of files is consistent otherwise, you need to make sure what you manipulate is a real number. I assume numbers are integers but of course you can change it. Extra precautions are required in this kind of project. I will leave it to you. The simplified code for the above procedure is
#include <QString>
#include <QFile>
#include <QDebug>
#include <QTextStream>
int main()
{
QFile data1("text1.txt");
if (!data1.open(QIODevice::ReadOnly | QIODevice::Text)){
qDebug() << "text1.txt file can't be opened...";
return -1;
}
QFile data2("text2.txt");
if (!data2.open(QIODevice::ReadOnly | QIODevice::Text)){
qDebug() << "text2.txt file can't be opened...";
return -1;
}
QTextStream in1(&data1), in2(&data2);
while ( !in1.atEnd() && !in2.atEnd() ) {
QString num1 = in1.readLine();
QString num2 = in2.readLine();
if ( num1.toInt() > num2.toInt() )
qDebug() << num1.toInt() << ">" << num2.toInt();
// do the rest of comparison
}
return 0;
}
Now in my case, the txt files are
text1.txt
1
2
3
4
text2.txt
3
5
1
6
The output is
3 > 1
Edit: the OP is looking for the difference and its sum.
int sum(0);
while ( !in1.atEnd() && !in2.atEnd() ) {
QString num1 = in1.readLine();
QString num2 = in2.readLine();
int result = num1.toInt() - num2.toInt();
qDebug() << num1.toInt() << "-" << num2.toInt() << " = " << result;
sum += result;
}
qDebug() << "sum = " << sum;
Basic approach would be something like this:
QString filename1("C:/Users/UserName/Downloads/t1.txt");
QString filename2("C:/Users/UserName/Downloads/t2.txt");
QFile file(filename1);
file.open(QIODevice::ReadOnly);
QTextStream in(&file);
QStringList textOfFile1;
while (!in.atEnd()) {
QString line = in.readLine();
textOfFile1.append(line);
}
QFile file2(filename2);
file2.open(QIODevice::ReadOnly);
QTextStream in2(&file2);
QStringList textOfFile2;
while (!in.atEnd()) {
QString line = in.readLine();
textOfFile2.append(line);
}
if(textOfFile1.size() != textOfFile2) return false;
for(int i = 0; i < textOfFile1.size(); i++)
{
if(textOfFile1[i] != textOfFile2[i]) return false;
}
return true;
i.e. You read the files into a QStringList and you compare the lists line by line. This way you can also catch the firs # of line where there was a mismatch. Note that such comparison also considers white spaces such as \n \t etc.
PS: wrap the readers into functions, to avoid duplication like me. :)
Hope this helps ;)

QString to double

void setNewValue(const QString& fhStr)
{
bool ok(false);
double d = fhStr.toDouble(&ok);
if (ok) {
m_newValue = d;
}
}
Passing "23" as fhStr; ok is always evaluating as false i.e., the converted value (d) is never being assigned to the m_newValue
Anything wrong here? Using cross-compiler to run on the ARM board.
http://doc.qt.io/qt-5/qstring.html#toDouble
You probably have some extra info in your string. Use qDebug() to see what is going on:
#include <QDebug>
// ...
void setNewValue(const QString& fhStr)
{
bool ok(false);
double d = fhStr.toDouble(&ok);
if (ok) {
m_newValue = d;
}
qDebug() << fhStr << ok << m_newValue;
}
If you have other information you want to remove from your string, use a QRegularExpression or .strip() or some other string operators to get just the number out.
http://doc.qt.io/qt-5/qregularexpression.html#details
Also look at QValidators.
http://doc.qt.io/qt-5/qvalidator.html#details
http://doc.qt.io/qt-5/qtwidgets-widgets-lineedits-example.html
Hope that helps.

Reading from .can files

I want to read .can files in Qt, I found out it is similiar to ini files so i used QSettings::IniFormat, i look for 2 attributes( say "rate" and "name").
code:
for(int i=0; i<files.count();i++)
{
QSettings file(files[i], QSettings::IniFormat);
QStringList keys = file.allKeys();
foreach(const QString& key, keys)
{
if(key.endsWith("/rate"))
{
QString Rate = file.value(key).toString();
qDebug() << Rate;
}
if(key.endsWith("/name"))
{
QString name = file.value(key).toString();
qDebug()<<name;
}
Problem is my can files has lot of "name" attribute, so this method is returning all the "name" attributes. I want to store the "name" attribute which the program finds right after "rate", there can be "name" attribute before "rate", so i just want to store the attribute which the program finds immediately after it finds "rate".
I don't know about .can files, I searched a little about them but couldn't find anything about them related to ini format.
Anyways, I rewrote your code to output the very first name attribute it finds after each rate encountered.
bool rateAttrFound = false;
for(int i=0; i<files.count();i++)
{
QSettings file(files[i], QSettings::IniFormat);
QStringList keys = file.allKeys();
foreach(const QString& key, keys)
{
if(key.endsWith("/rate"))
rateAttrFound = true;
if(key.endsWith("/name"))
{
if(rateAttrFound){
qDebug() << file.value(key).toString();
rateAttrFound = false;
}
}
}
}

Resources