c++, qt: write a date into a label - c++

I'm a novice to use c++ and morely qt. I've developed a multi-class software to calculate easter date. Now i'd like to write it to a label on button click, but i get a -i think- segmentation fault. My code is this -just a function, but please, ask if you want to see other parts-:
void MainWindow::on_btn_calcola_clicked()
{
Easter *e;
int anno = ui->text_anno->text().split(" ")[0].toInt();
int *date = e->dataPasqua(anno);
int giorno = date[0];
int mese = date[1];
QString d = QString::number(giorno);
QString m = QString::number(mese);
QString dataCompleta = d+"/"+m;
ui->lbl_result->setText(dataCompleta);
}
What's wrong? Thankyou so much!

Variable "e" is declared, but not initialized.
Possible solution is to use "make_unique" or simple new operator, like:
e = new Easter();

Tried a declaration like below for Easter object.
(Is better to avoid pointer when is not needed)
Easter e = Easter();
And in a second time, try to return a QList instead of a pointer in your function dataPasqua()
Is the two potential issues, the rest seems to be ok.

Related

How to initialize over a 100 QLabel in an efficient way

I want to have the ability to update over 100 labels, so I was going to put them in an array like this:
voltage_label_array[0] = this->ui->Voltage_0;
voltage_label_array[1] = this->ui->Voltage_1;
voltage_label_array[...] = this->ui->Voltage_2;
voltage_label_array[...n] = this->ui->Voltage_n;
and then have this method
void MainWindow::updateValue(int i, int voltage){
voltage_label_array[i]->setText(QString::number(voltage));
}
but having 100 lines to set this up seems like a bad idea. Is there a way I can initialize a QLabel array inside a for loop or something?
If you need to do this, something is horribly wrong with your design. But it is possible.
Assuming your labels are named Voltage_0 to Voltage_99:
for(int i = 0; i < 100; ++i) {
auto ptr = this->findChild<QLabel*>(QString("Voltage_%1").arg(i));
voltage_label_array[i] = ptr;
}
This "solution" uses Qt's runtime reflection and carries the expected performance penalties.
But if you need to display several similar values, look up QListWidget and similar classes.

qt ASSERT failure in QList<T>::at: "index out of range"

I am still relatively new to Qt and I have recently been working on a large project. When I attempt to run the project I get this error:
ASSERT failure in QList<T>::at: "index out of range", file c:\qt\qt5.3.0\5.3\msvc2013_64\include\qtcore\qlist.h, line 479
Just wondering if anyone knows what this means or how I might go about tracking down the source of the problem?
[edit] I believe that the addition of this code is causing the error
autAtom *aP = new autAtom(Principal);
autAtom *aQ = new autAtom(Principal);
autData *P = new autData (DataAtom, aP);
autData *Q = new autData (DataAtom, aQ);
autData *X = new autData (AnyData);
AUTPostulate *p;
autStatementList preList;
{
preList.clear();
//autData *d1 = new autData(NotHereData, X);
autStatement *pre1 = new autStatement(aP, believes, X);
autStatement *goal = new autStatement(aP, sees, X);
preList.append(pre1);
p = new AUTPostulate("BS", BS, goal, preList);
cout << "" << p->getString().toStdString() << endl;
AUTPostulates.append(p);
}
When this is taken out the tool runs fine.
I ran into a similar issue because I did a connect on itemChanged before populating the widget and then while populating my slot code was called. After I put in a guard that prevented signal handling during widget population, I found I could populate the widget fine and I could also handle the signal fine after. Hope this helps.
Index out of range means you're trying to access an index of a QList object, or maybe an object that is a subclass of a QList that does not exist. So if you have a QList with a length of 5 and you try to access index 5, it will be out of range.
Also, it looks like your code contains a lot of classes that are not standard to Qt or C++. At least I don't recognize them. It's difficult to say what's going on here without knowing about those classes.

Does this Qt code leak memory?

I try to learn more about programming by studying open source using
UML. The code I have found is in the stage between Qt 3 and Qt 4.
The project is not that active so I ask this question here. Maybe
I should add that the program using this code do run.
Note, I am a junior. I ask because I want to learn.
My question is simple:
Do this code leak memory?
If not, why ?
void warn(const QString & s) {
// not showed dialog to compute needed size
QDialog d_aux;
Q3VBoxLayout * vbox_aux = new Q3VBoxLayout(&d_aux);
vbox_aux->setMargin(5);
Q3TextEdit * e = new Q3TextEdit(&d_aux);
e->setText(s);
// showed dialog
QDialog * d = new QDialog;
d->setCaption("My caption");
Q3VBoxLayout * vbox = new Q3VBoxLayout(d);
vbox->setMargin(5);
Q3TextView * t = new Q3TextView(d);
QFontMetrics fm(QApplication::font());
int maxw = (MyWindow::get_workspace()->width() * 4) / 5;
int maxh = (MyWindow::get_workspace()->height() * 4) / 5;
int he = (e->lines() + 5) * fm.height();
t->setText(s);
t->setMinimumSize(maxw, (he > maxh) ? maxh : he);
vbox->addWidget(t);
d->show();
}
Thanks // JG
You have one: The QDialog * d = new QDialog; The other pointers got a parent instance which takes ownership of the pointers. (Please confirm it in the documentation of Q3VBoxLayout, Q3TextEdit and Q3TextView)
I think you are leaking memory, but it would be simple to verify with a program like valgrind on Linux and so on. Let us see what dynamic memory allocations you do in your function:
Q3VBoxLayout * vbox_aux = new Q3VBoxLayout(&d_aux);
That is alright because it gets a parent. Let us see the next:
Q3TextEdit * e = new Q3TextEdit(&d_aux);
That is also alright for the same reason above. Let us see the next:
QDialog * d = new QDialog;
Here, you problems begin to arise because the dialog does not have a parent. You have several ways of fixing it.
1) Assign a parent, although this might not be ideal in this case as you do not seem to have any parent'ish look in your code for this widget. That is, nothing that could really become the parent of it unlike your Qt application if you are using that. This fix may require some major rework depending on the whole context that you have shown.
2) Use a smart pointer, e.g. QPointer around it, so it will be managed for you automatically. That should have been available at the age of the code you are using. This may also need some code rework depending on more context that you have not provided.
Let us see the next dynamic memory allocation:
Q3VBoxLayout * vbox = new Q3VBoxLayout(d);
That is alright for the reasons mentioned before. Let us see the next and last:
Q3TextView * t = new Q3TextView(d);
That is also alright for the reasons mentioned before.

Dynamic array of objects

I'm aware that I could use something called std::vector, but I'm afraid it's not possible because of the course restrictions.
I need to make a dynamic extensible array of objects. The array should grow and grow when new objects need to be stored.
Here is the class that the array belongs to:
class TransactionList
{
private:
Transaction *trans;
int amountTransactions;
Transaction newTrans;
public:
TransactionList();
~TransactionList();
void read( istream &is );
void write( ostream &os );
void add( Transaction & newTrans );
double totalExpenses();
double hasPaid( string namnet );
double isDebted( string namnet );
//PersonList FixPersons();
};
The method "void add ( Transaction & newTrans )" is the one I need. And yes, I seriously have to do it pointer-style.
So far this method is totally incomplete and just not even close to functional. I've tried several different ways, but end up with a runtime error or just bollocks result.
void TransactionList::add(Transaction & newTrans)
{
Transaction* tempArrPtr;
amountTransactions++;
trans = new Transaction[amountTransactions]
trans[amountTransactions - 1] = newTrans;
}
What I want the method to do is to build an array of of Transaction-objects and grow in size while it gets more objects.
I hope I've written about my problem clearly and wish someone could give me a good answer.
I tried Googling, but I'm still stuck - otherwise I wouldn't have bothered asking :p
Also if someone could give some pointers about copy constructors, I'd be very thankful. In our course material they pretty much didn't even show what a copy constructor should look like. Just like "You need copy constuctors for deep copying, good luck!"
You should add a maxTransactions variable, which would indicate the allocated length of your trans* array, and initialize both ammountTransactions and maxTransactions with 0.
Your array would automatically double its size when we reach the limits of trans
void TransactionList::add(Transaction & newTrans)
{
if(amountTransactions == maxTransactions){ //we've reached the capacity of trans
//allocate a new array
Transaction* nuTrans = new Transaction[maxTransactions*2+1];
//copy the old values of trans into nuTrans
memcpy(nuTrans, trans, sizeof(Transaction)*maxTransactions);
//deallocate the old trans array
delete []trans;
//set trans to point at your newly allocated array
trans = nuTrans;
//update maxTransactions
maxTransactions = maxTransactions*2+1;
}
trans[amountTransactions] = newTrans;
amountTransactions++;
}
PS. I wrote it directly here, I didn't check it if it compiles as a whole or didn't debug the code. But I present it as an idea you could follow
Edit: Working example # http://ideone.com/uz1mE
When you add an object and the array is too small you need to create a new one with the correct or larger size, copy the data, delete the old one and replace it with your new one.
Copy constructors are just like ordinary constructors only that they take an object of the same type. Do remember take care of your pointers properly when doing this.
TransactionList(const TransactionList & o);
Now I finally managed to solve this puzzle. Turns out I wasn't paying enough attention to the fact that my Transaction-objects themselves held a dynamic array, so I finally came up with the idea of making an assign function to copy the objects. Thought I'd share my solution just in case any one has to tackle the same problem with the same limited set of tools.
This is how it ended up looking like:
void TransactionList::add(Transaction & newTrans)
{
amountTransactions++;
cout << "Adding a transaction-object to the array. amountTransactions = " << amountTransactions << endl;
//Allocate a new array
Transaction* tempTrans = new Transaction[amountTransactions];
//Copy the objects with the assign-function
for (int i = 0; i < amountTransactions - 1; i++)
tempTrans[i].assign(trans[i]);
//Delete the old one
delete[] trans;
//Set trans to point at the new one
trans = tempTrans;
//Add the newcomer object
trans[amountTransactions - 1].assign(newTrans);
}
And the assign-function looks as follows:
void Transaction::assign(const Transaction & t)
{
date = t.date;
type = t.type;
name = t.name;
amount = t.amount;
amountFriends = t.amountFriends;
cout << "Hello assign " << amountFriends << endl;
delete [] friends;
if (amountFriends > 0)
{
friends = new string[amountFriends];
for (int i = 0; i < amountFriends; i++)
friends[i] = t.friends[i];
}
else
friends = NULL;
}
I based my final solution on matyas' answer, so I owe you one buddy! :)
Thanks also to Alexandre C. for good read!
I'm not counting out the possibility there might be some error in the code, but at least it compiles, runs and produces correct result. Feel free to point out if you find something that's not right.

Retrieve value of QTableWidget cells which are QLineEdit widgets

I create a QLineEdit,set a validator and put it on the table with this code:
ui->moneyTableWidget->setCellWidget(rowsNum, 1, newQLineEdit);
Then I've got another class for manipulating the table's data doing the sum of every value of a column. Here's the code:
int Calculator::calculatePricesSum(QTableWidget &moneyTableWidget){
double total = 0;
QWidget *tmpLineEdit;
QString *tmpString;
for(int row=0; row<moneyTableWidget.rowCount(); row++){
tmpLineEdit = (QLineEdit*)moneyTableWidget.cellWidget(row,1);
tmpString = tmpLineEdit.text();
total += tmpString->toDouble();
}
return total;
}
But the building fails with this error:
/home/testpec/src/nokia
QT/MoneyTracker-build-simulator/../MoneyTracker/calculator.cpp:11:
error: cannot convert ‘QLineEdit*’ to
‘QWidget*’ in assignment
Why this convertion error?
Another subquestion: passing the table as reference saves memory right? Could this be the problem? Im developing for a Nokia smartphone and I think passing the object by value is a waste of memory...(sorry if is a dumb question but I'm a little rusty with C++ and all the pointers stuff...)
When you declare your tmpLineEdit, you should be declaring it as a QLineEdit* instead of a QWidget*. Your loop grabs the widget, casts it to a QLineEdit* and then tries to put it back into a QWidget*. Also, I'd recommend using qobject_cast<QLineEdit*> (or dynamic_cast) so that you can ensure the cast succeeded.
int Calculator::calculatePricesSum(QTableWidget &moneyTableWidget){
double total = 0;
QLineEdit* tmpLineEdit;
QString tmpString;
for(int row=0; row < moneyTableWidget.rowCount(); row++)
{
tmpLineEdit = qobject_cast<QLineEdit*>(moneyTableWidget.cellWidget(row,1));
if(NULL == tmpLineEdit)
{
// Do something to indicate failure.
}
tmpString = tmpLineEdit->text();
total += tmpString.toDouble();
}
return total;
}
As for your second question, passing by reference is probably a good idea - I know some of the classes in Qt (QImage in particular) use reference counting and implicit sharing so that you can pass around by value without worrying about the implications of large copy operations, but I'm not sure if a QTableWidget is in that category as well.