almdudler777
1st June 2014, 20:51
Hello qt-community,
i am currently doing my first little steps with qt inside qtcreator. the first things were really straight forward, which really is compliment for qt as a framework (developed with delphi and freepascal before). But now i came across somethings that i need an answer for. i must say in advance, that i am not used to develop with c/c++, but willing to learn it :)
First let me wrap up what i'm currently trying to do:
I have written a simple program with Turbo Delphi 2006 about 8 years ago, which i use as a database for my little movie-collection. it uses a sqlite backend to store the data. but the sql layout is not really professional. for example a movie has only one field for all cast-members (violating the sql normalization quite a bit). Thats what i want to solve before rebuilding the application in qt.
Following is my sample code (hope my comments help with understanding):
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("D:/Entw/Qt/dvdorganizer/database/data.sqlite3");
if(!db.open()){
qDebug("No Connection to Database");
}
QSqlQuery qry(db);
qry.exec("UPDATE dvds SET `titel` = replace(`titel`,\"\\'\",\"'\");");
qry.exec("UPDATE dvds SET `cast` = replace(`cast`,\"\\'\",\"'\");");
qry.exec("SELECT `cast`, `titel`, `id` FROM dvds WHERE trim(`cast`) != ''");
QStringList castList;
QTreeWidgetItem *actorItem;
QString left, right, full;
while(qry.next()){
castList.clear(); //empty the list, just to be sure...
//qry.value holds all castmembers for a film in the form of:
//Prename1 Name1, Prename2 Name2, ... , prenameN NameN therefor we split at the , char
castList = qry.value(0).toString().trimmed().split(",", QString::SkipEmptyParts);
for(int i = 0; i<castList.count(); i++){ //for every castmember 1 to N
full = castList.value(i).trimmed(); //complete name as found betwen , ... , (e.g. Angus T. Jones, ...)
left = full.left(full.lastIndexOf(" ")).trimmed(); //the guessed prename, currently also holds everything else
//like Angus T.
right = full.right(full.size() - full.lastIndexOf(" ")).trimmed(); //the surname e.g. Jones
//the treewidget was used to play around with it, but mainly for debugging purposes like wrong names
if(ui->treeWidget->findItems(full,Qt::MatchFixedString, 2).count() == 0){ //is there already an item for this actor
actorItem = new QTreeWidgetItem(ui->treeWidget); //create a new Widgetitem for this actor
actorItem->setText(0,left); //prename
actorItem->setText(1,right); //name
actorItem->setText(2,full); //full name (for debugging things mentioned in the example above)
actorItem->setText(3,qry.value(0).toString().trimmed()); //sql cell as in the resultcell with all castmembers
actorItem->setText(4,qry.value(1).toString().trimmed()); //movietitel
ui->treeWidget->addTopLevelItem(actorItem);
}
//following is used to fill the actorlist, which will later be used to transfer the data into atomic sql tables
if(actorList.contains(full)){ //if there is already one actor entry for this name
QHash<QString, Actor>::iterator iter = actorList.find(full);
iter.value().movieList.append(qry.value(2).toInt() ); //append the movie id to the actors movielist
}else{ //first appereance of this actor -> get a new item
Actor tmp; //isn't this created on the stack and should be gone after the end of this function????
tmp.movieList.append(qry.value(2).toInt()); //append the movie id to the actors movielistttttt
tmp.setName(right);
tmp.setPreName(left);
actorList.insert(full, tmp);
}
}
}
ui->treeWidget->sortItems(2,Qt::AscendingOrder); //sort the list on names ascending
QHash<QString, Actor>::iterator iter = actorList.begin(); //get an iterator at the beginning of the actorlist
//next part is to check the actorlist, just to see if this would fitt into the new sql tables
QString movies;
while (iter != actorList.end()) {
for (int i = 0; i < iter.value().movieList.size(); i++){ //for every movie_id in the actors movielist
qry.prepare("SELECT `titel` FROM dvds WHERE id = ? ");
qry.addBindValue(iter.value().movieList.at(i));
qry.exec();
if(qry.next())
movies += qry.value(0).toString() + ", ";
qry.clear();
}
//next will output something like; to the debug output
//"Chris" ; "Hemsworth" : "[BluRay] Thor, [BluRay] Marvel's The Avengers, The Cabin in the Woods, Thor - The Dark Kingdom, "
qDebug() << iter.value().getPreName() << ";" << iter.value().getName() << ": " << movies;
++iter;
movies.clear();
}
db.close();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
QMessageBox box;
Actor tmp = actorList.values().at(10);
box.setText(tmp.getName());
box.exec();
}
actor.h and actor.cpp
#include <QString>
#include <QList>
#ifndef ACTOR_H
#define ACTOR_H
class Actor
{
public:
Actor();
void setPreName(QString prename);
void setName(QString name);
const QString getName();
const QString getPreName();
QList<int> movieList;
private:
QString prename;
QString name;
};
#endif // ACTOR_H
//--------------------------------------------------------
#include "actor.h"
Actor::Actor()
{
}
void Actor::setName(QString name){ this->name = name; }
void Actor::setPreName(QString prename){ this->prename = prename; }
const QString Actor::getName(){ return this->name; }
const QString Actor::getPreName(){ return this->prename; }
My questions:
- first off: every suggestions are welcome (as for best practises), i'm well aware that the code itself is not really robust, meaning it lacks of some error handling
1) in line 25 i declared a pointer to an TreeWidgetItem which is then set to an instance of the same in line 43.
In Delphi i had a similar option: either could i create an item myself and add it with an addItem(pointer) to the widget or ask the widget to create one for me instead.
In my QT Project i added the widget as the parent in line 43. Will this automatically take care of freeing the space used by this item, when clearing the widget?
In Delphi this was not automatically the case, as i could pass the widget as a parent but still had to put the item in the widget by calling a adding function...
2) in line 57 i am creating an instance of my own actor class. as my comment already states: wouldn't this be created on the stack? as i do not use any malloc or new Actor() ???
in the pushbutton function i tested that and i can still use all those instances of my actors... i thought that when not calling new Actor() the instance is created on stack and would be gone after the function ends (the instance runs out of scope)
3) in line 67 i get an iterator to go through my list of actors. in many examples on the web i always saw them using ...::const_iterator iter = actorList.cbegin();
if i try that the compiler gives me:
D:\Entw\Qt\dvdorganizer\mainwindow.cpp:83: Fehler: passing 'const Actor' as 'this' argument of 'const QString Actor::getPreName()' discards qualifiers [-fpermissive]
qDebug() << iter.value().getPreName() << ";" << iter.value().getName() << ": " << movies;
^
from my understanding: i using the const_iterator nothing can be changed on the retrieved values. But does that count for my own class too? Either way, what really bothers me is that i do not want to change anything regarding the value. i just want to use a getter-method in line 83?!
Does anybody have a simple explanation for when to use const, what it does exactly? Maybe a good article about that?!
4) referring to lines 98,99
if i dont split that up into two lines:
box.setText(actorList.values().at(10).getName());
it gives me the same error as in question 3.
after splitting it up it works great?!
5)
void MainWindow::on_pushButton_clicked()
{
QMessageBox box;
Actor tmp = actorList.values().at(10);
box.setText(tmp.getName());
box.exec();
}
shouldn't tmp be a pointer, ie. Actor *tmp = ... because the real thing was already created before and i just need to reference it? when i do so, it gives me the const error again...
Maybe i am just still not confident with the pointer and scope things. again: i am just starting with c++ too :(
Hope this wasn't to noobie after all. Any help welcome. Thanks in advance.
Daniel
i am currently doing my first little steps with qt inside qtcreator. the first things were really straight forward, which really is compliment for qt as a framework (developed with delphi and freepascal before). But now i came across somethings that i need an answer for. i must say in advance, that i am not used to develop with c/c++, but willing to learn it :)
First let me wrap up what i'm currently trying to do:
I have written a simple program with Turbo Delphi 2006 about 8 years ago, which i use as a database for my little movie-collection. it uses a sqlite backend to store the data. but the sql layout is not really professional. for example a movie has only one field for all cast-members (violating the sql normalization quite a bit). Thats what i want to solve before rebuilding the application in qt.
Following is my sample code (hope my comments help with understanding):
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("D:/Entw/Qt/dvdorganizer/database/data.sqlite3");
if(!db.open()){
qDebug("No Connection to Database");
}
QSqlQuery qry(db);
qry.exec("UPDATE dvds SET `titel` = replace(`titel`,\"\\'\",\"'\");");
qry.exec("UPDATE dvds SET `cast` = replace(`cast`,\"\\'\",\"'\");");
qry.exec("SELECT `cast`, `titel`, `id` FROM dvds WHERE trim(`cast`) != ''");
QStringList castList;
QTreeWidgetItem *actorItem;
QString left, right, full;
while(qry.next()){
castList.clear(); //empty the list, just to be sure...
//qry.value holds all castmembers for a film in the form of:
//Prename1 Name1, Prename2 Name2, ... , prenameN NameN therefor we split at the , char
castList = qry.value(0).toString().trimmed().split(",", QString::SkipEmptyParts);
for(int i = 0; i<castList.count(); i++){ //for every castmember 1 to N
full = castList.value(i).trimmed(); //complete name as found betwen , ... , (e.g. Angus T. Jones, ...)
left = full.left(full.lastIndexOf(" ")).trimmed(); //the guessed prename, currently also holds everything else
//like Angus T.
right = full.right(full.size() - full.lastIndexOf(" ")).trimmed(); //the surname e.g. Jones
//the treewidget was used to play around with it, but mainly for debugging purposes like wrong names
if(ui->treeWidget->findItems(full,Qt::MatchFixedString, 2).count() == 0){ //is there already an item for this actor
actorItem = new QTreeWidgetItem(ui->treeWidget); //create a new Widgetitem for this actor
actorItem->setText(0,left); //prename
actorItem->setText(1,right); //name
actorItem->setText(2,full); //full name (for debugging things mentioned in the example above)
actorItem->setText(3,qry.value(0).toString().trimmed()); //sql cell as in the resultcell with all castmembers
actorItem->setText(4,qry.value(1).toString().trimmed()); //movietitel
ui->treeWidget->addTopLevelItem(actorItem);
}
//following is used to fill the actorlist, which will later be used to transfer the data into atomic sql tables
if(actorList.contains(full)){ //if there is already one actor entry for this name
QHash<QString, Actor>::iterator iter = actorList.find(full);
iter.value().movieList.append(qry.value(2).toInt() ); //append the movie id to the actors movielist
}else{ //first appereance of this actor -> get a new item
Actor tmp; //isn't this created on the stack and should be gone after the end of this function????
tmp.movieList.append(qry.value(2).toInt()); //append the movie id to the actors movielistttttt
tmp.setName(right);
tmp.setPreName(left);
actorList.insert(full, tmp);
}
}
}
ui->treeWidget->sortItems(2,Qt::AscendingOrder); //sort the list on names ascending
QHash<QString, Actor>::iterator iter = actorList.begin(); //get an iterator at the beginning of the actorlist
//next part is to check the actorlist, just to see if this would fitt into the new sql tables
QString movies;
while (iter != actorList.end()) {
for (int i = 0; i < iter.value().movieList.size(); i++){ //for every movie_id in the actors movielist
qry.prepare("SELECT `titel` FROM dvds WHERE id = ? ");
qry.addBindValue(iter.value().movieList.at(i));
qry.exec();
if(qry.next())
movies += qry.value(0).toString() + ", ";
qry.clear();
}
//next will output something like; to the debug output
//"Chris" ; "Hemsworth" : "[BluRay] Thor, [BluRay] Marvel's The Avengers, The Cabin in the Woods, Thor - The Dark Kingdom, "
qDebug() << iter.value().getPreName() << ";" << iter.value().getName() << ": " << movies;
++iter;
movies.clear();
}
db.close();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
QMessageBox box;
Actor tmp = actorList.values().at(10);
box.setText(tmp.getName());
box.exec();
}
actor.h and actor.cpp
#include <QString>
#include <QList>
#ifndef ACTOR_H
#define ACTOR_H
class Actor
{
public:
Actor();
void setPreName(QString prename);
void setName(QString name);
const QString getName();
const QString getPreName();
QList<int> movieList;
private:
QString prename;
QString name;
};
#endif // ACTOR_H
//--------------------------------------------------------
#include "actor.h"
Actor::Actor()
{
}
void Actor::setName(QString name){ this->name = name; }
void Actor::setPreName(QString prename){ this->prename = prename; }
const QString Actor::getName(){ return this->name; }
const QString Actor::getPreName(){ return this->prename; }
My questions:
- first off: every suggestions are welcome (as for best practises), i'm well aware that the code itself is not really robust, meaning it lacks of some error handling
1) in line 25 i declared a pointer to an TreeWidgetItem which is then set to an instance of the same in line 43.
In Delphi i had a similar option: either could i create an item myself and add it with an addItem(pointer) to the widget or ask the widget to create one for me instead.
In my QT Project i added the widget as the parent in line 43. Will this automatically take care of freeing the space used by this item, when clearing the widget?
In Delphi this was not automatically the case, as i could pass the widget as a parent but still had to put the item in the widget by calling a adding function...
2) in line 57 i am creating an instance of my own actor class. as my comment already states: wouldn't this be created on the stack? as i do not use any malloc or new Actor() ???
in the pushbutton function i tested that and i can still use all those instances of my actors... i thought that when not calling new Actor() the instance is created on stack and would be gone after the function ends (the instance runs out of scope)
3) in line 67 i get an iterator to go through my list of actors. in many examples on the web i always saw them using ...::const_iterator iter = actorList.cbegin();
if i try that the compiler gives me:
D:\Entw\Qt\dvdorganizer\mainwindow.cpp:83: Fehler: passing 'const Actor' as 'this' argument of 'const QString Actor::getPreName()' discards qualifiers [-fpermissive]
qDebug() << iter.value().getPreName() << ";" << iter.value().getName() << ": " << movies;
^
from my understanding: i using the const_iterator nothing can be changed on the retrieved values. But does that count for my own class too? Either way, what really bothers me is that i do not want to change anything regarding the value. i just want to use a getter-method in line 83?!
Does anybody have a simple explanation for when to use const, what it does exactly? Maybe a good article about that?!
4) referring to lines 98,99
if i dont split that up into two lines:
box.setText(actorList.values().at(10).getName());
it gives me the same error as in question 3.
after splitting it up it works great?!
5)
void MainWindow::on_pushButton_clicked()
{
QMessageBox box;
Actor tmp = actorList.values().at(10);
box.setText(tmp.getName());
box.exec();
}
shouldn't tmp be a pointer, ie. Actor *tmp = ... because the real thing was already created before and i just need to reference it? when i do so, it gives me the const error again...
Maybe i am just still not confident with the pointer and scope things. again: i am just starting with c++ too :(
Hope this wasn't to noobie after all. Any help welcome. Thanks in advance.
Daniel