how can I verify if multiple checkboxes are checked - c++

std::string output;
if ((checkbox1->isChecked() && checkbox2->isChecked()) &&
(!checkbox3->isChecked() || !checkbox4->isChecked() || !checkbox5->isChecked() || !checkbox6->isChecked()))
{
output = " Using Checkbox: 1, 2 ";
}
if ((checkbox1->isChecked() && checkbox2->isChecked() && checkbox3->isChecked()) &&
(!checkbox4->isChecked() || !checkbox5->isChecked() || !checkbox6->isChecked()))
{
output = " Using Checkbox: 1, 2, 3 ";
}
....
using QT creator how can I verify how many checkboxes have been checked and change the output string accordingly?
with multiple if statements it's not working due to me getting confused with all those NOT AND OR.
and it takes a long time to code all possibilities.

All your checkBoxes should be in groupBox
Try this:
QList<QCheckBox *> allButtons = ui->groupBox->findChildren<QCheckBox *>();
qDebug() <<allButtons.size();
for(int i = 0; i < allButtons.size(); ++i)
{
if(allButtons.at(i)->isChecked())
qDebug() << "Use" << allButtons.at(i)->text()<< i;//or what you need
}

Use an array of checkboxes like this
// h-file
#include <vector>
class MyForm {
...
std::vector< QCheckBox* > m_checkBoxes;
};
// cpp-file
MyForm::MyForm() {
...
m_checkBoxes.push_back( checkbox1 );
m_checkBoxes.push_back( checkbox2 );
...
m_checkBoxes.push_back( checkbox5 );
}
...
output = " Using Checkbox:";
for ( int i = 0, size = m_checkBoxes.size(); i < size; ++i ) {
if ( m_checkBoxes[ i ]->isChecked() ) {
output += std::to_string( i + 1 ) + ", ";
}
}

TLDR: Place them in a container and build your string by iterating over them.
Code:
// line taken from #Chernobyl
QList<QCheckBox *> allButtons = ui->groupBox->findChildren<QCheckBox *>();
auto index = 1;
std::ostringstream outputBuffer;
outputBuffer << "Using Checkbox: ";
for(const auto checkBox: allButtons)
{
if(checkBox->isChecked())
outputBuffer << index << ", ";
++index;
}
auto output = outputBuffer.str();

Use QString instead of std::string and then:
QCheckBox* checkboxes[6];
checkbox[0] = checkbox1;
checkbox[1] = checkbox2;
checkbox[2] = checkbox3;
checkbox[3] = checkbox4;
checkbox[4] = checkbox5;
checkbox[5] = checkbox6;
QStringList usedCheckboxes;
for (int i = 0; i < 6; i++)
{
if (checkbox[i]->isChecked())
usedCheckboxes << QString::number(i+1);
}
QString output = " Using Checkbox: " + usedCheckboxes.join(", ") + " ";
This is just an example, but there's numerous ways to implement this. You could keep your checkboxes in the QList which is a class field, so you don't have to "build" the checkboxes array every time. You could also use QString::arg() instead of + operator for string when you build the output, etc, etc.
What I've proposed is just a quick example.

Related

QList request item from array not giving correct reference

Apologies if the title is incorrectly phrased - I am not too sure what is causing the problem
I am testing QList array access and came across this. It is a straight forward example of using referencing QList append() function and QList[] operator.
Aim:
I am trying to find out whether adding the same object (created with new) to 2 QList<int> and changing one of those objects (or references rather) will change the other.
What I found seems to indicate this is not true given my example and the output below:
// Some structure to simluate an object
struct IntStream {
int i;
};
// Create our lists
QList<IntStream> newlist = QList<IntStream>();
QList<IntStream> another = QList<IntStream>();
// Add 3 IntStream objects to the 2 lists using the same object, printing out the object and its reference
for (int i = 0; i < 3; i++) {
IntStream *s = new IntStream;
s->i = i;
newlist.append(*s);
another.append(*s);
qDebug() << QString("%1[%2] = %3 (").arg("newList", QString::number(i), QString::number(i)) << &another[i] << ")";
qDebug() << QString("%1[%2] = %3 (").arg("another", QString::number(i), QString::number(i)) << &another[i] << ")";
}
// Alter bject at index 1 with some arbitrary value
for (int i = 0; i < 3; i++) {
if(newlist.at(i).i == 1) {
qDebug() << "another[1] = " << &another[i];
qDebug() << "newList[1] = " << &newlist[i];
another[i].i = 4;
}
}
// Here, I should see the 2 values match, they do not
qDebug() << QString("%1 == %2 ???").arg(QString::number(newlist.at(1).i), QString::number(another.at(1).i));
The output of this is:
"newList[0] = 0 (" 0x27c75f88 )
"another[0] = 0 (" 0x27c75f88 )
"newList[1] = 1 (" 0x27c755d0 )
"another[1] = 1 (" 0x27c755d0 )
"newList[2] = 2 (" 0x27c75630 )
"another[2] = 2 (" 0x27c75630 )
another[1] = 0x27c755d0
newList[1] = 0x27c76ef0
"1 == 4 ???"
Should I expect to see 4 == 4 or did I do something wrong somewhere?
Notes:
I am using the T &QList::operator[](int i), not const T &QList::operator[](int i) const
Creating new objects rather than storing scoped objects
qDebug() << QString("%1[%2] = %3 (").arg("newList", QString::number(i), QString::number(i)) << &another[i] << ")";
qDebug() << QString("%1[%2] = %3 (").arg("another", QString::number(i), QString::number(i)) << &another[i] << ")";
You compared twice the &another[i]. You should write &newlist[i] instead in the first line.
And when you call newlist.append(*s); you made a copy of your IntStream instance.
To answer to your need :
"I am trying to find out whether adding the same object (created with new) to 2 QList and changing one of those objects (or references rather) will change the other."
Use a shared_ptr to shared your instance between multiple list.
Something like :
struct IntStream {
int i;
};
// Create our lists
QList<std::shared_ptr<IntStream >> newlist = QList<std::shared_ptr<IntStream >>();
QList<std::shared_ptr<IntStream >> another = QList<std::shared_ptr<IntStream >>();
// Add 3 IntStream objects to the 2 lists using the same object, printing out the object and its reference
for (int i = 0; i < 3; i++) {
std::shared_ptr<IntStream > s = std::make_shared<IntStream >();
s->i = i;
newlist.append(s);
another.append(s);

QStringList in QT c++

I want to assign each item of a string list to another string list, like:
stringlist_1 = ("k*k1*k2" , "s*s1*s2" , "b*b1*b2")
I want to make them like this :
stringlist_2 = ("k","k","k2")
stringlist_3 = ("s","s1","s2")
etc..
how can I make that?
I tray to use this code
for (int i=0 ; i<2 ; i++)
{
QStringList d = stringlist_1.value(i).split("*");
qDebug()<< d ;
}
I use a for loop becuase my list it is very big, but
the problem is with storing all strings of primary list in same stringlist (d).
How can I let a for loop change the stringlist which assigned to it in each loop?
Is there another way I could achieve that?
You can create a vector of string lists:
#include <QtCore>
QVector<QStringList> splitTerms(const QStringList & source)
{
QVector<QStringList> result;
result.reserve(source.count());
for (auto src : source)
result.append(src.split(QChar('*'), QString::SkipEmptyParts));
return result;
}
int main() {
qDebug() << splitTerms(QStringList{"k*k1*k2", "s*s1*s2", "b*b1*b2"});
}
Output:
QVector(("k", "k1", "k2"), ("s", "s1", "s2"), ("b", "b1", "b2"))
Can you just split it and assign again?
for (int i=0 ; i<2 ; i++)
{
QStringList d = stringlist_1.value(i).split("*");
qDebug()<< d ;
+ foreach (const QString &s, d) {
+ QStringList dd;
+ dd << s;
+ qDebug() << dd;
+ }
}

C++ Replace Value in Config File

I am trying to replace a value in a configuration file. It can be edited in a text editor.
[MODEL]
...
Latitude = 1.034
Longitude = 110.58334
...
How can I search for the keyword "Latitude" and replace "1.034" with another value? (e.g. 1.04)
Edit: Thanks for the down votes. I have attached my code below:
QFile fileReadModels(CP1);
fileReadModels.open(QIODevice::ReadOnly | QIODevice::Text);
QTextStream inModels(&fileReadModels);
while(!inModels.atEnd())
{
QString lineModels = inModels.readLine();
if(lineModels.isNull())
{
break;
}
else
{
strListInModels.append(lineModels);
}
}
fileReadModels.close();
int startFlag = 0;
int stopFlag = 0;
for(int i = 1; i <= strListInModels.count(); i++)
{
if(strListInModels[i].contains("Latitude", Qt::CaseInsensitive) == 1)
{
//! get start position
startFlag = i - 1;
//! get stop position
stopFlag = i + 2;
break;
}
}
//! get data from start till start position
for(int x = 0; x <= startFlag; x++)
{
strListOutModels << strListInModels[x];
}
//! insert in Ownship1 lat/lon
QString os1LatStr = " Latitude = " + os1Lat;
QString os1LonStr = " Longitude = " + os1Lon;
strListOutModels << os1LatStr;
strListOutModels << os1LonStr;
//! get data from stop postion till end
for(int y = stopFlag; y < strListInModels.count(); y++)
{
strListOutModels << strListInModels[y];
}
//! write to file
QFile fileWriteModels(CP1);
fileWriteModels.open(QIODevice::ReadWrite | QIODevice::Truncate);
QTextStream outModels(&fileWriteModels);
QString qStrModels = strListOutModels.join("\r");
outModels << qStrModels;
fileWriteModels.close();
You can use QSettings feature
location.ini
[MODEL]
Latitude = 1.034
Longitude = 110.58334
You can use QSetting to modify your data
//Access your datafile
QSettings settings("location.ini", QSettings::IniFormat);
//Read Data
QString sLatitude = settings.value("MODEL/Latitude").toString();
//Write Data
settings.setValue("MODEL/Latitude", "18.55");

How to prepare statements and bind parameters in Postgresql for C++

I'm quite new to C++ and know a little bit about pqxx library. What I want to implement is to prepare statements and bind parameters. In PHP I'm used to doing this in such a nice and concise manner:
$s = $db->prepare("SELECT id FROM mytable WHERE id = :id");
$s->bindParam(':id', $id);
$s->execute();
or using tokens:
$data = array();
$data[] = 1;
$data[] = 2;
$s = $db->prepare("SELECT id FROM mytable WHERE id = ? or id = ?");
$s->execute($data);
I tried to fugure out from pqxx documentation how to implement this, but to me documentation looks like a mess and lacks short and simple examples (like I provided above). I hope someone can also provide such simple examples (or of comparable simplicity - without having to write some behemoth code) when dealing with Postgresql in C++.
A simple example. This just prints the number of entries with id value 0.
#include<pqxx/pqxx>
#include<iostream>
int main()
{
std::string name = "name";
int id = 0;
try {
//established connection to data base
pqxx::connection c("dbname=mydb user=keutoi");
pqxx::work w(c);
//statement template
c.prepare("example", "SELECT id FROM mytable WHERE id = $1");
//invocation as in varible binding
pqxx::result r = w.prepared("example")(id).exec();
w.commit();
//result handling for accessing arrays and conversions look at docs
std::cout << r.size() << std::endl;
}
catch(const std::exception &e)
{
std::cerr << e.what() << std::endl;
return 1;
}
return 0;
}
The function w.prepared() is a bit convoluted. It's similar to a curried(curry) function in haskell, as in it takes a parameter and returns another function which in turn takes another parameter. That kind of thing.
Documentation says:
How do you pass those parameters? C++ has no good way to let you pass an unlimited, variable number of arguments to a function call, and the compiler does not know how many you are going to pass. There's a trick for that: you can treat the value you get back from prepared as a function, which you call to pass a parameter. What you get back from that call is the same again, so you can call it again to pass another parameter and so on.
Once you've passed all parameters in this way, you invoke the statement with the parameters by calling exec on the invocation
If there are more parameters use $1 $2 and so on in the prepare function.
c.prepare("SELECT id name FROM mytable WHERE id = $1 AND name = $2")
and give the varibles as
w.prepared("example")(dollar1_var)(dollar2_var).exec()
An Example for dynamic preparation
#include<pqxx/pqxx>
#include<iostream>
#include<vector>
//Just give a vector of data you can change the template<int> to any data type
pqxx::prepare::invocation& prep_dynamic(std::vector<int> data, pqxx::prepare::invocation& inv)
{
for(auto data_val : data)
inv(data_val);
return inv;
}
int main()
{
std::string name = "name";
//a data array to be used.
std::vector<int> ids;
ids.push_back(0);
ids.push_back(1);
try {
pqxx::connection c("dbname=mydb user=keutoi");
pqxx::work w(c);
c.prepare("example", "SELECT id FROM mytable WHERE id = $1 or id = $2");
pqxx::prepare::invocation w_invocation = w.prepared("example");
//dynamic array preparation
prep_dynamic(ids, w_invocation);
//executing prepared invocation.
pqxx::result r = w_invocation.exec();
w.commit();
std::cout << r.size() << std::endl;
}
catch(const std::exception &e)
{
std::cerr << e.what() << std::endl;
return 1;
}
return 0;
}
if you want to handle other data types use this function definition
template<class T> pqxx::prepare::invocation& prep_dynamic(std::vector<T> data, pqxx::prepare::invocation& inv)
{
for(auto data_val : data)
inv(data_val);
return inv;
}
Use pqxx::prepare::invocation where you can, and bind more values before execution, because it's more stable and error preventative, but there is a faster way as I describe it below.
I.
With invocation:
pqxx::nontransaction W(C);
std::string m_insertCommand = "INSERT INTO tableforperftest(column1, column2) VALUES";
unsigned int m_nCurrentRow = 32767;
for (size_t i = 0; i < m_nCurrentRow; i++)
{
unsigned int countOf$ = i * 2;
for (unsigned int i = 0; i < 2; ++i)
{
if (i == 0)
{
m_insertCommand += "(";
}
else
{
m_insertCommand += ", ";
}
m_insertCommand += "$";
std::stringstream ss;
ss << countOf$ + i + 1;
m_insertCommand += ss.str();
}
if(i < m_nCurrentRow - 1)
m_insertCommand += ") ,";
}
m_insertCommand += ")";
C.prepare("insert_into_db", m_insertCommand);
pqxx::prepare::invocation inv = W.prepared("insert_into_db");
for (size_t i = 0; i < m_nCurrentRow; i++)
{
inv(i)(i);
}
inv.exec();
II.
With stored procedure which gets more values for parameters:
CREATE OR REPLACE FUNCTION insertintoboosted(valuesforinsert TEXT) RETURNS VOID AS
$$
BEGIN
EXECUTE 'INSERT INTO tableforperftestproof(column1, column2) VALUES (' || valuesforinsert || ')';
END;
$$
LANGUAGE plpgsql;
Code:
for (size_t i = 0; i < m_nCurrentRow; i++)
{
if (i == 0)
ss << i << "," << i;
else
ss << "(" << i << "," << i;
if (i < m_nCurrentRow - 1)
ss << "),";
}
C.prepare("prep2", "select insertintoboosted($1::text)");
W.prepared("prep2")(ss).exec();
III.
With parameter bindings and execution for each time:
std::string m_insertCommand3 = "INSERT INTO tableforperftest(column1, column2) VALUES ($1, $2)";
C.prepare("insert_into_db3", m_insertCommand3);
for (size_t i = 0; i < m_nCurrentRow; i++)
{
W.prepared("insert_into_db3")(i)(i).exec();
}
To compare the solutions with 32767 inserts:
Invocation: --> Elapsed: 0.250292s
Stored Proc: --> Elapsed: 0.154507s
Parameter binding + execution each time: --> Elapsed: 29.5566s

foreach loop in QT not working in this example?

I generally never get caught in looping. But looks like I am clueless here on the looping logic. When I put a break in the inner for loop, the values I get is always 0. However, when I remove break, I get the right values. What is wrong in my code?
void ContentCache::getAggregatorList()
{
TLOG_FUNC_ENTER();
ContentAggregator *aggregator = ContentAggregator::Instance();
QList <ContentID> aggContentList;
/* Get the service list from the aggregator */
aggregator->getContentList(CONTENT_TYPE_LIVE_SERVICE, aggContentList);
QList<Attribute> attributeListOut;
ContentID content;
foreach( content, aggContentList )
{
TLOG_INFO("SJ..main loop");
//if(content.source == TERRESTRIAL_BROADCAST_SOURCE )
// {
doGetServiceAttributes(content,attributeListOut);
unsigned int attributeIndex = 0;
foreach( Attribute attr, attributeListOut)
{
TLOG_INFO("SJ..Inner loop");
if(attr.name == "chanNum")
{
TLOG_INFO("SJ..The attr channelNum is = "<<attr.value.toInt());
if( attr.value.toUInt() == 999)
{
TLOG_INFO("SJ..The changed attr channelNum is"<<attr.value.toUInt());
attr.name = "chanNum";
attr.value = 200;
attributeListOut.replace(attributeIndex,attr);
TLOG_INFO("SJ..The changed attr channelNum is"<<attr.value.toUInt());
m_cacheDB->terrestrialUpdateService(content,attributeListOut);
}
else
{
TLOG_INFO("SJ..The unmodified attr channelNum is"<<attr.value.toUInt());
}
break;
}
attributeIndex++;
// }
}
}
// getAttributeValues(ContentID id, QList<QString> value, QList<Attribute> &attributeListOut);
}*
Without the break, you're counting all Attributes. With the break, you're only counting attributes up to the first one that has attr.name == "chanNum" which doesn't seem likely to be useful. It's not entirely clear what you intended the break to do.
One way to help with such things is to pull out just the logic and try it in a simplified form. For example (in C++11 form):
#include <iostream>
#include <string>
int main()
{
std::string string1{"BONGO"};
std::string string2{"This is string2"};
std::cout << "With the break\n";
for ( auto ch : string1 )
{
unsigned int attributeIndex = 0;
for( auto c: string2 )
{
if( c > 'a')
{
if( c > 'i')
{
std::cout << ch << c << "+";
}
else
{
std::cout << ch << c << "-";
}
break;
}
std::cout << ch << c << "#";
attributeIndex++;
}
std::cout << attributeIndex << '\n';
}
std::cout << "Without the break\n";
for ( auto ch : string1 )
{
unsigned int attributeIndex = 0;
for( auto c: string2 )
{
if( c > 'a')
{
if( c > 'i')
{
std::cout << ch << c << "+";
}
else
{
std::cout << ch << c << "-";
}
// no break
}
std::cout << ch << c << "#";
attributeIndex++;
}
std::cout << attributeIndex << '\n';
}
}
This produces the following output:
With the break
BT#Bh-1
OT#Oh-1
NT#Nh-1
GT#Gh-1
OT#Oh-1
Without the break
BT#Bh-Bh#Bi-Bi#Bs+Bs#B #Bi-Bi#Bs+Bs#B #Bs+Bs#Bt+Bt#Br+Br#Bi-Bi#Bn+Bn#Bg-Bg#B2#15
OT#Oh-Oh#Oi-Oi#Os+Os#O #Oi-Oi#Os+Os#O #Os+Os#Ot+Ot#Or+Or#Oi-Oi#On+On#Og-Og#O2#15
NT#Nh-Nh#Ni-Ni#Ns+Ns#N #Ni-Ni#Ns+Ns#N #Ns+Ns#Nt+Nt#Nr+Nr#Ni-Ni#Nn+Nn#Ng-Ng#N2#15
GT#Gh-Gh#Gi-Gi#Gs+Gs#G #Gi-Gi#Gs+Gs#G #Gs+Gs#Gt+Gt#Gr+Gr#Gi-Gi#Gn+Gn#Gg-Gg#G2#15
OT#Oh-Oh#Oi-Oi#Os+Os#O #Oi-Oi#Os+Os#O #Os+Os#Ot+Ot#Or+Or#Oi-Oi#On+On#Og-Og#O2#15
Using techniques like this can help you work out the logic abstractly and then code with confidence in the real project.
I missed clearing up the object - under pressure.Here is the silly solution to my silly problem. QList attributeListOut was not getting over-written, in fact it gets appended here. This was the problem. This should not be the case ideally. But, it all depends on how the operators are overloaded.
void ContentCache::getAggregatorList()
{
TLOG_FUNC_ENTER();
ContentAggregator *aggregator = ContentAggregator::Instance();
QList <ContentID> aggContentList;
/* Get the service list from the aggregator */
aggregator->getContentList(CONTENT_TYPE_LIVE_SERVICE, aggContentList);
QList<Attribute> attributeListOut;
ContentID content;
foreach( content, aggContentList )
{
TLOG_INFO("SJ..main loop");
//if(content.source == TERRESTRIAL_BROADCAST_SOURCE )
// {
attributeListOut.clear();
doGetServiceAttributes(content,attributeListOut);
unsigned int attributeIndex = 0;
foreach( Attribute attr, attributeListOut)
{
TLOG_INFO("SJ..Inner loop");
if(attr.name == "chanNum")
{
TLOG_INFO("SJ..The attr channelNum is = "<<attr.value.toInt());
if( attr.value.toUInt() == 999)
{
TLOG_INFO("SJ..The changed attr channelNum is"<<attr.value.toUInt());
attr.name = "chanNum";
attr.value = 200;
attributeListOut.replace(attributeIndex,attr);
TLOG_INFO("SJ..The changed attr channelNum is"<<attr.value.toUInt());
m_cacheDB->terrestrialUpdateService(content,attributeListOut);
}
else
{
TLOG_INFO("SJ..The unmodified attr channelNum is"<<attr.value.toUInt());
}
break;
}
attributeIndex++;
// }
}
}
// getAttributeValues(ContentID id, QList<QString> value, QList<Attribute> &attributeListOut);
}*