PDA

View Full Version : Passing ACTUAL variable to a new class, getting wrong value



trainer92
21st August 2016, 20:54
Hello everyone, I'm new to QT/C++ and I'm probably missing something essential and I can't make it to work.

I explain a bit.

I have 2 classes (*MainWindow.cpp/.h* and *SimulationTask.cpp/.h*).

MainWindow got a Menu that's using some variables to load via SQL the info.
Once user has clicked the last item on the list, it loads from SQL database a string with the name of our new variable, called tablename.

Now we have a second window, called SimulationTask that needs the variable tablename, but every time I use it, it uses it with its default value defined in mainwindow.h, instead of the actual value, as we did get in our mainwindow.cpp.

The code is long already, I will show you the essential parts so you can contrast.


//Get table method(at MainWindow.cpp)

QString MainWindow::getTableName()

connOpen();
QSqlQuery query;
query.prepare("SELECT candata_table,bitrate "
"FROM system_list, maker_data "
"WHERE system_list.specific_id=maker_data.specific_id "
"AND system_list.specific_id="
"(SELECT maker_data.specific_id FROM maker_data WHERE maker_data.manufacturer='"+varmnf+"' AND maker_data.model='"+varmodel+"' AND maker_data.year='"+varyear+"')");
query.exec();
query.first();
connClose();
tablename = query.value(0).toString();

qDebug() << (query.lastQuery());

return tablename;


If I call it on my MainWindow.cpp class, in a pushbutton for example, it does load values in Sql query (**varmnf , varmodel, varyear**) perfectly and it returns tablename without problem, but if I call it from my simulationTask.cpp, it get initializacion values for varmnf , varmodel, varyear, so obviously, the query doesnt throw any result, and tablename either.



#include "mainwindow.h"
//TABLE NAME (at simulationstask.cpp)
MainWindow mainwindow;

mainwindow.getTableName(); // --> This is returning tablename = ''
qDebug() << ("Hello");
qDebug() << (tablename);

**Console Output**
[Console Log image][1]


[1]: http://i.stack.imgur.com/ZADL6.jpg


This is my MainWindow.h:


#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "simulationtask.h"

#define debugprefix << __LINE__ << " "
namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT


public:

QString getTableName();

//FUNCTIONS VARIABLES
QSqlDatabase mydb;

QString varmnf;
QString varmodel;
QString varyear;
QString tablename;
QString tablenameUpdated;
QString bitrate;
QString varsystem;


This is part of my MainWindow.cpp:


#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMessageBox>
#include "simulationtask.h"

void MainWindow::on_ModelList_clicked(const QModelIndex &index)
{
//cleaning
ui->System_list->setModel(emptymodal);
varsystem="";
tablename="";
bitrate="";

QString var2=ui->ModelList->model()->data(index).toString();
varmodel=ui->ModelList->model()->data(index).toString();
connOpen();
QSqlQueryModel * modal=new QSqlQueryModel();
QSqlQuery* query=new QSqlQuery(mydb);

query->prepare("SELECT year FROM maker_data WHERE manufacturer='"+varmnf+"' AND model='"+var2+"'");
query->exec();
modal->setQuery(*query);
ui->YearList->setModel(modal);
connClose();

qDebug() <<(query->lastQuery());

}
void MainWindow::on_mnfList_clicked(const QModelIndex &index){codehere}
void MainWindow::on_YearList_clicked(const QModelIndex &index){codehere}

Basically what It do is update on click the index and send to my variables (mnfvar [manufacturer] -> modelvar[model] -> yearvar [fabrication year] -> systemvar [type os system] ) With those variables with the correct values from SQL, I can call the function above (that's another query) to get tablename. The problem comes when I call it from simulationTask.cpp, and it doesnt have those variables, I tried returning tablename in function but it's not working.

Also tried with get and set methods and not working, I tried a dirty way too, I make a LineTextEdit in 1st window UI, where I sent my tablename record, well, when loading from 2nd window UI it also loads the INITIALIZED value "test" (and not the actual one being showed "gpunto")... I think it's something bad with headers or ui initialization because it's not normal.

anda_skoa
21st August 2016, 20:59
Your code in simulationTask.cpp calls getTableName() on a new, local, MainWindow object.

Cheers,
_

trainer92
21st August 2016, 21:04
Hello anda_skoa!

So I guess there must be a way to call it on the same "instance"?

How could I do that?

Thanks!

EDIT:

Here are images of my program and console log:
12084
12085
12086

anda_skoa
21st August 2016, 22:18
So I guess there must be a way to call it on the same "instance"?

How could I do that?

By calling the method on that instance.

Since your code doesn't show how the relation between SimulationTask and MainWindow is (or I missed it) it is hard to make any suggestions on getting access to that instance.
Maybe you don't even need to do that at all.

E.g. SimulationTask instance might be created in MainWindow and the they could just get the relevant values right then.

Cheers,
_

jefftee
21st August 2016, 22:42
You should also use QSqlQuery::bindValue instead of concatenating variables in-line with the SQL as your code may be vulnerable to SQL injection attacks.

trainer92
21st August 2016, 23:03
By calling the method on that instance.

Since your code doesn't show how the relation between SimulationTask and MainWindow is (or I missed it) it is hard to make any suggestions on getting access to that instance.
Maybe you don't even need to do that at all.

E.g. SimulationTask instance might be created in MainWindow and the they could just get the relevant values right then.

Cheers,
_

Hello, I attach a diagram explaining how it works.

12087

In general fact, MainWindow is holding all SQL thing (Manufacturers, and model, year, system.. all loaded via SQL and outputed to QViewList in program). Once user navigate to last category, I got a query getting the Tablename needed, that's also at SQL tables, so I get it and store on a variable called "tablename".

Now I have class MainWindow, with loaded menu, and tablename variable

I need class SimulationTask, to get this variable, to perform its work, but I can't find a way to pass it.

(SimulationTask is called with a button with the following code):


simulationTask *simulationtask;
simulationtask =new simulationTask(this);
simulationtask->show();

Then a new UI opens, and I need the values from MainWindow, but I'm spending like 8hours with that stupid thing and I cant get it <_>.

Thanks for your help!


You should also use QSqlQuery::bindValue instead of concatenating variables in-line with the SQL as your code may be vulnerable to SQL injection attacks.

I will get a view on this, thanks!

jefftee
21st August 2016, 23:18
You could pass a MainWindow* to your simulationtask constructor, which you'd then save as a simulationtask member variable. Then add getter/setter methods to MainWindow to get/set the variables you need, i.e.:


QString MainWindow::getFoo()
{
return m_foo;
}

void MainWindow::setFoo(const QString& foo)
{
m_foo = foo;
}


Edit: In fact, your post above shows you passing "this" to the simulationtask constructor. Is "this" the MainWindow instance? If so, just save that value in a simulationtask member variable and then you can use that to get the values once you add getter methods like so: m_mainwindow->getFoo(), etc.

trainer92
21st August 2016, 23:33
You could pass a MainWindow* to your simulationtask constructor, which you'd then save as a simulationtask member variable. Then add getter/setter methods to MainWindow to get/set the variables you need, i.e.:


QString MainWindow::getFoo()
{
return m_foo;
}

void MainWindow::setFoo(const QString& foo)
{
m_foo = foo;
}


Edit: In fact, your post above shows you passing "this" to the simulationtask constructor. Is "this" the MainWindow instance? If so, just save that value in a simulationtask member variable and then you can use that to get the values once you add getter methods like so: m_mainwindow->getFoo(), etc.

Hello!! Thanks a lot for suggestions, I openned eyes with last post from anda_skoa


By calling the method on that instance.

Since your code doesn't show how the relation between SimulationTask and MainWindow is (or I missed it) it is hard to make any suggestions on getting access to that instance.
Maybe you don't even need to do that at all.

E.g. SimulationTask instance might be created in MainWindow and the they could just get the relevant values right then.

Cheers,
_

I though on.. "Why not do this inversed?".. and this is what i done, I just did set the variable of simulationtask from my mainwindow class as follow:


In mainwindow.cpp
simulationTask *simulationtask;
simulationtask =new simulationTask(this);

simulationtask->finalTablename = setTableName(); <--- This return me the famous "tablename" value x)

simulationtask->show();


I have been here for over 8 hours for this.. I feel stupid, but this is how it works.. :)

Thanks everyone for your help, it's really appreaciated! ^^