PDA

View Full Version : Trying to learn. Not declared in this scope error



poporacer
21st September 2010, 03:26
I am trying to create a main window and if a SQLite file doesn't exist, then create one. Then populate a combobox with data from a query. I am using QT Creator. I am learning and would like to know why I get the error and not just the correct code if that isn't too much to ask.


//database.h
//Database functions will go here
#ifndef DATABASE_H
#define DATABASE_H

class database
{
public:
database();
};

#endif // DATABASE_H



//MainWindow.h
#ifndef MXMAINWINDOW_H
#define MXMAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MXMainWindow;
}

class MXMainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MXMainWindow(QWidget *parent = 0);
~MXMainWindow();

private:
Ui::MXMainWindow *ui;
};

#endif // MXMAINWINDOW_H


//database.cpp
#include "database.h"
#include <QtSql>
#include <QApplication>
#include <QtGui>

bool createConnection()
{
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("rider.mt");
if (!db.open()) {
QMessageBox::warning(0, QObject::tr("Database Error"),
db.lastError().text());
return false;
}


QSqlQuery dbquery;
dbquery.prepare ("CREATE TABLE Rider (firstname varchar(20))");
dbquery.exec();
dbquery.prepare("insert into Rider (firstname)Jeremy')");
dbquery.exec("insert into Rider values('Ricky', 'Charmichael')");
dbquery.exec("insert into Rider values('Chad', 'Reed')");
dbquery.next();
QString strTest=dbquery.value(0).toString();
QString strTest2= dbquery.value(1).toString();
return true;
}


//mainwindow.cpp
#include "mxmainwindow.h"
#include "ui_mxmainwindow.h"
#include <QtSql>
#include "database.h"

MXMainWindow::MXMainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MXMainWindow)
{
ui->setupUi(this);
while (dbquery.next()) //Error here.. dbquery not declared in this scope
{
ui->cmbName->addItem(dbquery.value(0).toString());
}
}

MXMainWindow::~MXMainWindow()
{
delete ui;
}

//main.cpp
#include <QtGui/QApplication>
#include "mxmainwindow.h"
#include <QtSql>
#include <QtGui>
bool createConnection()
{
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("mxtrainer.dat");
if (!db.open()) {
QMessageBox::warning(0, QObject::tr("Database Error"),
db.lastError().text());
return false;
}
return true;
}

void createDb()
{
QSqlQuery query;
//query.exec("DROP TABLE scooter");

query.exec("CREATE TABLE rider ("
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
"name VARCHAR(20) NOT NULL, "
"weight INTEGER NOT NULL, ");
query.exec("INSERT INTO rider (name, weight) "
"VALUES ('Villapoto', 155");
query.exec("INSERT INTO rider (name, weight) "
"VALUES ('Carmichael', 165");
query.exec("INSERT INTO rider (name, weight) "
"VALUES ('McGrath', 175");

}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
bool create = !QFile::exists("mxtrainer.dat");
if (!createConnection())
return 1;
if (create)
createDb();
MXMainWindow w;
w.show();

return a.exec();
}

I thought by including the header file of where the declaration is made it would provide the scope? What is the problem with this?
Thanks

ChrisW67
21st September 2010, 03:40
Variables local to a function or method are not visible outside that function. dbQuery is a local variable created on the stack inside your createConnection() function and cannot be seen inside the MXMainWindow constructor where you try to use it. Apart from not being visible outside createConnection(), dbQuery ceases to exist at the end of the function.

In any case, I cannot see a query that would return the rows you are expecting to populate the combo box with e.g. "SELECT name FROM riders".

poporacer
21st September 2010, 04:33
I was basing my code on http://doc.qt.nokia.com/4.6/sql-cachedtable.html and they use the connection and query in the connection.h file and it seems to work. What am I doing wrong? I did forget the query to populate the rows. In trying to make things work I duplicated making the table. I would like to have the connection and queries in a header file but I don't know why it doesn't work like the example. I moved the query to the mxmainwindow the program compiles but there is no data in the combobox.
I see that the mxtrainer.dat file is created but there is no data in it.
So my questions are:
1. Why didn't my program work like the example where the connection and query were in a seperate header file
2. Why isn't the mxtrainer.dat file being populated?
3. Why isn't the combobox getting populated? (Maybe because of #2!!)
Suggested code corrections?

Here is the new code:

//mxmainwindow.h
#ifndef MXMAINWINDOW_H
#define MXMAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MXMainWindow;
}

class MXMainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MXMainWindow(QWidget *parent = 0);
~MXMainWindow();

private:
Ui::MXMainWindow *ui;
};

#endif // MXMAINWINDOW_H

//mxmainwindow.cpp
#include "mxmainwindow.h"
#include "ui_mxmainwindow.h"
#include <QtSql>
//#include "database.h"

MXMainWindow::MXMainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MXMainWindow)
{
ui->setupUi(this);

QSqlQuery dbquery;
dbquery.prepare ("SELECT name from rider");
dbquery.exec();

while (dbquery.next())
{
ui->cmbName->addItem(dbquery.value(0).toString());
}
}

MXMainWindow::~MXMainWindow()
{
delete ui;
}


//main.cpp
#include <QtSql>
#include <QtGui>
bool createConnection()
{
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("mxtrainer.dat");
if (!db.open()) {
QMessageBox::warning(0, QObject::tr("Database Error"),
db.lastError().text());
return false;
}
return true;
}

void createDb()
{
QSqlQuery query;
//query.exec("DROP TABLE scooter");

query.exec("CREATE TABLE rider ("
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
"name VARCHAR(20) NOT NULL, "
"weight INTEGER NOT NULL, ");
query.exec("INSERT INTO rider (name, weight) "
"VALUES ('Villapoto', 155");
query.exec("INSERT INTO rider (name, weight) "
"VALUES ('Carmichael', 165");
query.exec("INSERT INTO rider (name, weight) "
"VALUES ('McGrath', 175");

}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
bool create = !QFile::exists("mxtrainer.dat");
if (!createConnection())
return 1;
if (create)
createDb();
MXMainWindow w;
w.show();

return a.exec();
}

ChrisW67
21st September 2010, 04:52
1. Your original program didn't compile because it was not valid C++. This is not about what is in which file: it would have failed even if you put all the code in the same file.
2. You only call createDb() if the "mxtrainer.dat" file does not exist already. What happens if it exists but is empty?
3. Quite possibly because of 2. If you look at QSqlQuery::lastError() after your call to exec() you might see a clue.

You have a tool for single stepping through your program can be very useful here.

poporacer
21st September 2010, 05:08
What do I need to do to have the connection and queries in the header file? If put the function in to test if the mxtrainer is there to see if it is the first time the program has run. If it is the first time, create the table. If not use the existing data. Where is the tool for single stepping through the code...I have been using breakpoints to try and find the problems. I got rid of the test and put in QSqlQuery::Last error like this:

void createDb()
{
QSqlQuery query;
//query.exec("DROP TABLE scooter");

query.exec("CREATE TABLE rider ("
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
"name VARCHAR(20) NOT NULL, "
"weight INTEGER NOT NULL, ");
query.exec("INSERT INTO rider (name, weight) "
"VALUES ('Villapoto', 155");
query.exec("INSERT INTO rider (name, weight) "
"VALUES ('Carmichael', 165");
query.exec("INSERT INTO rider (name, weight) "
"VALUES ('McGrath', 175");
qDebug() << query.lastError();
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//bool create = !QFile::exists("mxtrainer.dat");
//if (!createConnection())
//return 1;
//if (create)
createDb();
MXMainWindow w;
w.show();

return a.exec();
}
I got an error database not open.
Where do I go from here?
PS. I really appreciate all your help!!

ChrisW67
21st September 2010, 05:36
The "Database not open error" is the result of commenting out the createConnection() call, which is opening the database! In your previous attempt the error you would be really interested in was the exec() call after trying to select the rider's names.

The debugging tool you are setting breakpoints in can single-step your program. Look on the Debug menu in Qt Creator when you are stopped at a break point.

I don't know exactly what you mean by "What do I need to do to have the connection and queries in the header file?". You just put the code there and make sure it is included where required. However, it is usually not a good idea to put real implementation code into header files (with the exception of trivial inline methods). The Qt examples do this to simplify the construction of many independent programs that use that example database. Headers are typically expected to contain declarations only, with the implementation (if any) in a matching cpp file.

poporacer
21st September 2010, 05:59
I uncommented out that section and got the error QSqlError(1, "Unable to execute statement", "near "175": syntax error") And stepping in goes through the QT code. Am I missing something?
And when I put in after the Select name query I got: QSqlError(-1, "Unable to fetch row", "No query")

ChrisW67
21st September 2010, 06:19
Your SQL INSERT statements are malformed: missing their closing )

Edit: So is your create table.

poporacer
22nd September 2010, 01:01
Thank you so much...I am starting to figure this out a little bit at a time. I really appreciate your help!
The program works and the combo box gets populated, but in the QSqlError message I get
QSqlError(-1, "", "")
QSqlError(-1, "", "")
I couldn't find any reference to what the -1 or the "","" errors are. Any Ideas?

ChrisW67
22nd September 2010, 04:19
I think (not near a machine to test) that QSqlError::isValid() would return false... no error.

Lykurg
22nd September 2010, 06:20
I think (not near a machine to test) that QSqlError::isValid() would return false... no error.

You are right, -1 indicates that there is no error. To see if a statement was successful fetch the result of QSqlQuery::exec()