Subclassing: QAbstractItemModel has no member - c++

I am relatively new to C++ and the Qt Framework. I tried to implement a simple QTableView with a custom model derived from QAbstractListModel.
If I call
model->appendRow("Test");
in my main application, everything works perfectly fine. However, if I call
table->model()->appendRow("Test");
I get the following build-error:
'class QAbstractItemModel' has no member named 'appendRow'
table->model()->appendRow("Test");
^
What am I missing?
Sourcecode:
main.c
#include <QApplication>
#include <QTableView>
#include "exercises.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QTableView *table = new QTableView();
exercisesModel *model = new exercisesModel();
table->setModel(model);
model->appendRow("Test"); //why does this work...
table->model()->appendRow("Test"); //...and this doesn't?
table->show();
return a.exec();
}
exercises.h
#ifndef EXERCISES_H
#define EXERCISES_H
#include <QWidget>
#include <QAbstractListModel>
class exercisesModel : public QAbstractListModel
{
public:
exercisesModel(QObject *parent = 0);
int rowCount(const QModelIndex &parent) const;
QVariant data(const QModelIndex &index, int role) const;
bool appendRow(QString data);
private:
QList <QString> lst;
};
#endif // EXERCISES_H
exercises.c
#include "exercises.h"
#include <QDebug>
exercisesModel::exercisesModel(QObject *parent) : QAbstractListModel(parent){
}
int exercisesModel::rowCount(const QModelIndex &parent) const{
Q_UNUSED(parent);
return this->lst.size();
}
QVariant exercisesModel::data(const QModelIndex &index, int role) const{
if(this->lst.size() != 0){
if (role == Qt::DisplayRole){
return this->lst[index.row()];
}
return QVariant();
}
return QVariant();
}
bool exercisesModel::appendRow(QString data){
int lastElemPos = this->lst.size();
beginInsertRows(QModelIndex(), lastElemPos, lastElemPos);
this->lst << data;
endInsertRows();
return true;
}

The QTableView::model() member function returns a pointer to a QAbstractItemModel. That is all the compiler knows about the type at the time you call table->model()->appendRow("Test"). It doesn't know that your derived model is what is actually being pointed to. There are a few ways this could be handled.
One way is to use a cast:
static_cast<exercisesModel*>(table->model())->appendRow("Test")
Now you are explicitly telling the compiler "I know that the actual type of the object is exercisesModel", so it can treat it appopriately.
As noted by Kuba Ober, Qt has its own cast that will verify that the type is correct
qobject_cast<exercisesModel*>(table->model())->appendRow("Test")
This is better than static_cast, but this check will only be done at run-time, and the more problems you can catch during compiling, the better.
The best option may be to keep the pointer to your exercisesModel and use that, so there is no question about what the underlying type is.

Because table->model() returns a QAbstractItemModel, and QAbstractItemModel does not have appendRow function you declared in exerciseModel, which is a child class of QAbstractItemModel. The compiler cannot know the actual type the table stored.
To access appendRow from table->model(), you need a type-casting:
exercisesModel *model = qobject_cast<exercisesModel *>(table->model());
// dynamic_cast could also be used.
Q_ASSERT(model);
model->appendRow("Test");

Related

Qt signal slot button

I need to change my text in QLabel every time when I clicked in order to my info updates.
When I change the value of A, the value of B must change, too.
I have two button that can change values in two QLabel (value of A, value of B).
main.cpp:
Counter A, B;
QObject::connect(&A, &Counter::changeValue, &B, &Counter::setValue);
QObject::connect(&A, &Counter::changeValue, &B, &Counter::Increment);
QObject::connect(&A, &Counter::changeValue, &B, &Counter::Decrement );
QObject::connect(Add, &QPushButton::clicked, &A, &Counter::clickedAdd(QLabel* obj));
QObject::connect(Sub, &QPushButton::clicked, &B, &Counter::clickedSub(QLabel* obj));
class Counter: public QObject{
private:
int count;
public slots:
int Increment () {
count++;
emit changeValue(count);
}
int Decrement () {
count--;
emit changeValue(count);
}
void clickedAdd(QLabel* obj){
int new_count = Increment();
obj_label->setText(QString::number(new_count));_
}
void clickedSub(QLabel* obj){
int new_count = Deccrement();
obj_label->setText(QString::number(new_count));_
}
void setValue(int new_count){
m_count = new_count;
emit changeValue(new_count);
}
public signals:
void changeValue(int);
How can I change my text in two QLabel's? Because in this way it stays const - 0....
When I try to connect:
QObject::connect(Add, &QPushButton::clicked, &A, &Counter::clickedAdd(QLabel* obj));
It writes an error:
Call to non-static member function without an object argument.
But I pass the function an argument - QLabel*.
Assuming OP wants an application with
two counters which can be incremented and decremented
a GUI
displaying the counter values
buttons to increment/decrement the counters interactively.
From this requirement, I would derive the structure of the program:
a class for the Counter (as already exposed by OP)
a GUI.
For the latter, I often saw classes as well in numerous sample codes but I believe: for such a minimal GUI / application, this could even all be done in main() directly.
testQCounter.cc:
#include <iostream>
#include <string>
// Qt header:
#include <QtWidgets>
// OPs Counter Class
class Counter : public QObject {
Q_OBJECT
private:
int count = 0;
public slots:
int Increment() {
count++;
emit changeValue(count);
return count;
}
int Decrement() {
count--;
emit changeValue(count);
return count;
}
int getValue() const { return count; }
void setValue(int new_count) {
count = new_count;
emit changeValue(new_count);
}
signals:
void changeValue(int);
};
#include "testQCounter.moc"
void setLabelValue(QLabel& qLbl, int value)
{
qLbl.setText(QString::number(value));
}
// main application
int main(int argc, char **argv)
{
qDebug() << "Qt Version:" << QT_VERSION_STR;
QApplication app(argc, argv);
// setup data
Counter a, b;
// setup GUI
QWidget qWinMain;
qWinMain.setWindowTitle("Counter Sample");
QGridLayout qGrid;
QLabel qLblATitle("Counter A");
qGrid.addWidget(&qLblATitle, 0, 0);
QPushButton qBtnIncA("+");
qGrid.addWidget(&qBtnIncA, 1, 0);
QLabel qLblA;
qLblA.setAlignment(Qt::AlignRight);
qLblA.setFrameStyle(QLabel::Box);
qGrid.addWidget(&qLblA, 2, 0);
QPushButton qBtnDecA("-");
qGrid.addWidget(&qBtnDecA, 3, 0);
QLabel qLblBTitle("Counter B");
qGrid.addWidget(&qLblBTitle, 0, 1);
QPushButton qBtnIncB("+");
qGrid.addWidget(&qBtnIncB, 1, 1);
QLabel qLblB("");
qLblB.setAlignment(Qt::AlignRight);
qLblB.setFrameStyle(QLabel::Box);
qGrid.addWidget(&qLblB, 2, 1);
QPushButton qBtnDecB("-");
qGrid.addWidget(&qBtnDecB, 3, 1);
qWinMain.setLayout(&qGrid);
qWinMain.show();
setLabelValue(qLblA, a.getValue());
setLabelValue(qLblB, b.getValue());
// install signal handlers
// connect clicked signal of buttons to counter a
QObject::connect(&qBtnDecA, &QPushButton::clicked, &a, &Counter::Decrement);
QObject::connect(&qBtnIncA, &QPushButton::clicked, &a, &Counter::Increment);
// connect changeValue signal of counter a to a function
QObject::connect(&a, &Counter::changeValue,
[&](int value) { setLabelValue(qLblA, value); });
// connect clicked signal of buttons to counter b
QObject::connect(&qBtnDecB, &QPushButton::clicked, &b, &Counter::Decrement);
QObject::connect(&qBtnIncB, &QPushButton::clicked, &b, &Counter::Increment);
// connect changeValue signal of counter b to b function
QObject::connect(&b, &Counter::changeValue,
[&](int value) { setLabelValue(qLblB, value); });
// runtime loop
return app.exec();
}
Output:
Qt Version: 5.15.1
Notes:
Concerning the update of the counter value label:
The signature of QLabel::setText() (the potential slot) is void QLabel::setText(const QString&).
The signature of the signal to connect is void Counter::changeValue(int).
Obviously, these signatures are not compatible.
For convenience, I introduced a function
void setLabelValue(QLabel& qLbl, int value)
{
qLbl.setText(QString::number(value));
}
but this doesn't fix the incompatibility because the function still has another parameter QLabel& which is not in the emitted signal.
This is a very usual case and the very usual solution is to bind the resp. QLabel reference to the signal.
It can be done most easily using a lambda.
When I first saw lambdas in C++, I found the syntax non-intuitive and somehow scaring.
However, after having read the doc. and tutorials I got used to it, and today, I couldn't imagine to live without.
I must admit before I learnt about lambdas I had to fiddle with bind() and hide() (in gtkmm with sigc++). This was a real nightmare…
Counter defines a signal. (I fixed the wrong syntax of OP.)
To make this linking properly, I had to add some things:
Q_OBJECT
#include "testQCounter.moc"
support for the Qt moc in my build script.
My build script is a Visual Studio project which I prepared with a CMake script.
I had to extend my CMakeLists.txt for moc (as I usually build without moc).
The CMakeLists.txt used to build the build script for testQCounter.cc:
project(QCounter)
cmake_minimum_required(VERSION 3.10.0)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
find_package(Qt5 COMPONENTS Widgets REQUIRED)
set(CMAKE_AUTOMOC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
include_directories("${CMAKE_SOURCE_DIR}")
add_executable(testQCounter testQCounter.cc)
target_link_libraries(testQCounter Qt5::Widgets)
For my production, I would use separate classes for the GUI stuff as well, of course.
So, considering that the sample has two counters with nearly identical GUIs, it may make sense to introduce a counter widget – CounterEdit.
testQCounter2.cc:
#include <iostream>
#include <string>
// Qt header:
#include <QtWidgets>
// OPs Counter Class
class Counter : public QObject {
Q_OBJECT
private:
int count = 0;
public slots:
int Increment() {
count++;
emit changeValue(count);
return count;
}
int Decrement() {
count--;
emit changeValue(count);
return count;
}
int value() const { return count; }
void setValue(int new_count) {
count = new_count;
emit changeValue(new_count);
}
signals:
void changeValue(int);
};
#include "testQCounter2.moc"
class CounterEdit : public QWidget {
private:
Counter* pCounter = nullptr;
QVBoxLayout qVBox;
QLabel qLblTitle;
QPushButton qBtnInc;
QLabel qLblValue;
QPushButton qBtnDec;
QMetaObject::Connection connectionInc;
QMetaObject::Connection connectionDec;
QMetaObject::Connection connectionValue;
public:
CounterEdit(const QString& title, QWidget* pQParent = nullptr) :
QWidget(pQParent),
qLblTitle(title),
qBtnInc("+"),
qLblValue(""),
qBtnDec("-")
{
qLblTitle.setAlignment(Qt::AlignCenter);
qVBox.addWidget(&qLblTitle);
qVBox.addWidget(&qBtnInc);
qLblValue.setAlignment(Qt::AlignRight);
qLblValue.setFrameStyle(QLabel::Box);
qVBox.addWidget(&qLblValue);
qVBox.addWidget(&qBtnDec);
setLayout(&qVBox);
}
virtual ~CounterEdit()
{
QObject::disconnect(connectionInc);
QObject::disconnect(connectionDec);
QObject::disconnect(connectionValue);
}
CounterEdit(const CounterEdit&) = delete;
CounterEdit& operator=(const CounterEdit&) = delete;
Counter* counter() { return pCounter; }
const Counter* counter() const { return pCounter; }
void updateValue();
void updatevalue(int) { updateValue(); }
void setCounter(Counter* pCounter);
};
void CounterEdit::updateValue()
{
if (pCounter) {
qLblValue.setText(QString::number(pCounter->value()));
} else {
qLblValue.setText(QString());
}
}
void CounterEdit::setCounter(Counter* pCounter)
{
QObject::disconnect(connectionInc);
QObject::disconnect(connectionDec);
QObject::disconnect(connectionValue);
this->pCounter = pCounter;
if (pCounter) {
qLblValue.setText(QString::number(pCounter->value()));
connectionInc
= QObject::connect(&qBtnInc, &QPushButton::clicked, pCounter, &Counter::Increment);
connectionDec
= QObject::connect(&qBtnDec, &QPushButton::clicked, pCounter, &Counter::Decrement);
connectionValue
= QObject::connect(pCounter, &Counter::changeValue, this, &CounterEdit::updateValue);
}
}
// main application
int main(int argc, char **argv)
{
qDebug() << "Qt Version:" << QT_VERSION_STR;
QApplication app(argc, argv);
// setup data
Counter a, b;
// setup GUI
QWidget qWinMain;
qWinMain.setWindowTitle("Counter Sample");
QHBoxLayout qHBox;
CounterEdit editA("Counter A:");
qHBox.addWidget(&editA);
CounterEdit editB("Counter B:");
qHBox.addWidget(&editB);
qWinMain.setLayout(&qHBox);
qWinMain.show();
editA.setCounter(&a);
editB.setCounter(&b);
// runtime loop
return app.exec();
}
Output:
Qt Version: 5.15.1
Notes:
As data model and GUI are not anymore hardwired by design, I changed the management of the signal-slot connections a bit:
The connections are done on demand (in CounterEdit::setCounter()).
Connections are disconnected when not anymore needed.
It's not strictly necessary to store the connections like I did in the sample.
In Qt, a connection may be disconnected as well by providing signal and slot like in connect().
I don't like this for two reasons:
I'm paranoid.
This won't work for lambdas.
While the actual member function for update (CounterEdit::updateValue()) is parameter-less, I provided a second flavor (CounterEdit::updateValue(int)) which is just a wrapper.
However, this 2nd flavor has an identical signature like Counter::changeValue() and, hence, can be used as slot without an adapter.

Why? Must construct a QApplication before a QWidget or pointer trouble?

I am trying to make a very simple Qt application that will display a table that is referenced from another class. that's it.
I have class UWRegModel, which takes a pointer to a vector of vectors as a parameter for the constructor.
When I build the vector in my main method and pass a reference, everything works fine, but I need to pass a reference to a vector that is contained in another class. This class has a method to get that pointer, but when I initialize this way, the program crashes with the following error:
QWidget: Must construct a QApplication before a QWidget
I'm guessing there is some kind of problem with the reference, and that it has nothing to do with a widget being created before an application. However, there is no compile error, and that is all I'm getting.
Here is the code:
uwregmodel.h
#ifndef UWREGMODEL_H
#define UWREGMODEL_H
#include <QAbstractTableModel>
#include <vector>
#include <string>
#include <bitset>
class UWRegModel : public QAbstractTableModel
{
Q_OBJECT
public:
UWRegModel(QObject *parent = 0, std::vector<std::vector<int>> *uregs = 0);
int rowCount(const QModelIndex &parent = QModelIndex()) const ;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
};
#endif // UWREGMODEL_H
uwregmodel.cpp
#include "uwregmodel.h"
std::vector<std::vector<int>>* _uregs = NULL;
UWRegModel::UWRegModel(QObject *parent, std::vector<std::vector<int> > *uregs) :QAbstractTableModel(parent)
{
_uregs = uregs;
}
int UWRegModel::rowCount(const QModelIndex & ) const
{
return (_uregs->at(0)).size();
}
int UWRegModel::columnCount(const QModelIndex &) const
{
return _uregs->size();
}
std::string intToBits(int x){
std::bitset<32> _x(x);
return _x.to_string();
}
QVariant UWRegModel::data(const QModelIndex &index, int role) const
{
if (role == Qt::DisplayRole)
{
std::string bin = intToBits((_uregs->at(index.column())).at(index.row()));
QString res = QString::fromStdString(bin);
return res;
}
return QVariant();
}
the main class
#include <QApplication>
#include <QPushButton>
#include <QtGui>
#include <QTableView>
#include <QtWidgets>
#include "uwregmodel.h"
#include "uwsimgui.h"
#include "ram.h"
#include "uwcpu.h"
int main(int argc, char **argv)
{
QApplication app (argc, argv);
UWCPU cpu(32,8,8);
QMainWindow w;
QTableView tableView;
UWRegModel myModel(0,cpu.getUREGs());
tableView.setModel( &myModel );
QHBoxLayout *hbox = new QHBoxLayout;
hbox->addWidget(&tableView);
QWidget *centralw = new QWidget;
centralw->setLayout(hbox);
w.setCentralWidget(centralw);
w.show();
return app.exec();
}
The UWCPU (uwcpu.cpp) class is very large, but here is the constructor and getUREGs method, only the relevant parts, I think:
int WORD_SIZE; //Ultraword will be WORD_SIZE^2
int NUM_BLOCKS;
int NUM_UREGS;
int NUM_REGS;
std::vector<std::vector<int>> UREG;
UWCPU::UWCPU(int _wordsize, int _uregs, int _regs){
WORD_SIZE = _wordsize;
NUM_BLOCKS = _wordsize;//Ultraword will be WORD_SIZE^2
NUM_UREGS = _uregs;
NUM_REGS = _regs;
for(int i = 0; i<NUM_UREGS; i++){
UREG.push_back(std::vector<int>(WORD_SIZE,0));
}
}
std::vector<std::vector<int>>* UWCPU::getUREGs(){
return &UREG;
}
Any help would be greatly appreciated, I've been stuck for a while and can't seem to get anywhere. I googled this pretty hard, but unfortunately it seems most people who get this error had problems with Qt libraries and versions. I don't think this is my case, I am using Qt creator, with version 5.8, and have tried running with debug and release versions and it makes no difference.

How to convert enum to QString?

I am trying to use the Qt reflection for converting enum to QString.
Here is the part of code:
class ModelApple
{
Q_GADGET
Q_ENUMS(AppleType)
public:
enum AppleType {
Big,
Small
}
}
And here is i trying to do:
convertEnumToQString(ModelApple::Big)
Return "Big"
Is this possible?
If you have any idea about convertEnumToQString, please share it
You need to use Q_ENUM macro, which registers an enum type with the meta-object system.
enum AppleType {
Big,
Small
};
Q_ENUM(AppleType)
And now you can use the QMetaEnum class to access meta-data about an enumerator.
QMetaEnum metaEnum = QMetaEnum::fromType<ModelApple::AppleType>();
qDebug() << metaEnum.valueToKey(ModelApple::Big);
Here is a generic template for such utility:
template<typename QEnum>
std::string QtEnumToString (const QEnum value)
{
return std::string(QMetaEnum::fromType<QEnum>().valueToKey(value));
}
Much more elegant way found (Qt 5.9), just one single line, with the help of mighty QVariant.
turns enum into string:
QString theBig = QVariant::fromValue(ModelApple::Big).toString();
Perhaps you don't need QMetaEnum anymore.
Sample code here:
ModelApple (no need to claim Q_DECLARE_METATYE)
class ModelApple : public QObject
{
Q_OBJECT
public:
enum AppleType {
Big,
Small
};
Q_ENUM(AppleType)
explicit ModelApple(QObject *parent = nullptr);
};
And I create a widget application, calling QVaraint function there :
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <modelapple.h>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QString s = QVariant::fromValue(ModelApple::Big).toString();
qDebug() << s;
}
MainWindow::~MainWindow()
{
delete ui;
}
You can see that i try to output the string on console , which really did:
And sorry for reverse casting , i tried successfully in some project , but some how this time i met compiling error. So i decide to remove it from my answer.
The following should get you going:
QString convertEnumToQString(ModelApple::AppleType type) {
const QMetaObject metaObject = ModelApple::staticMetaObject;
int enumIndex = metaObject.indexOfEnumerator("AppleType");
if(enumIndex == -1) {
/* The enum does not contain the specified enum */
return "";
}
QMetaEnum en = metaObject.enumerator(enumIndex);
return QString(en.valueToKey(type));
}
For the global Enum declaring use this in any header file:
namespace YourNamespace {
Q_NAMESPACE
enum YourEnum: int {
EnumValue1,
EnumValue2
};
Q_ENUM_NS(YourEnum)
}
and this where you want to get Enum description:
QMetaEnum metaEnum = QMetaEnum::fromType<YourEnum>();
qDebug() << "Enum description: " << metaEnum.name() << "::" << metaEnum.valueToKey(YourEnum::EnumValue2);
How about:
QString convertEnumToQString(ModelApple::AppleType type)
{
const QMetaObject &mo = ModelApple::staticMetaObject;
int index = mo.indexOfEnumerator("AppleType");
QMetaEnum metaEnum = mo.enumerator(index);
return metaEnum.valueToKey(type);
}
UPDATED: For Qt 5.5, see this answer
I faced the same problem and this is how i solved it. This is especially for Qt 4.8
QString string = enumToString(ModelApple::Big);
QString ModelApple::enumToString(AppleType apple)
{
int index = metaObject()->indexOfEnumerator("AppleType");
QMetaEnum metaEnum = metaObject()->enumerator(index);
return metaEnum.valueToKey(apple);
}

QML QSettings and QML - Cannot save/load settings

What I do wrong ? I always have in debug console-"error! cannot load data". Can anyone point out an error? Maybe I create bad "settings" ? It's a permission program problem?
//main.cpp
#include <QtGui/QGuiApplication>
#include "qtquick2applicationviewer.h"
#include <QQmlContext>
#include <QSettings>
#include "settings.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QtQuick2ApplicationViewer viewer;
viewer.setMainQmlFile(QStringLiteral("qml/kon/main.qml"));
Settings* settings = new Settings();
viewer.rootContext()->setContextProperty("settings", settings);
viewer.showExpanded();
return app.exec();
}
//settings.h
#ifndef SETTINGS_H
#define SETTINGS_H
#include <QObject>
#include <QSettings>
class Settings : public QSettings {
Q_OBJECT
public:
Settings(QObject *parent = 0);
virtual ~Settings();
Q_INVOKABLE
void setValue(const QString &key, const QVariant &value);
Q_INVOKABLE
void setValueIfNotSet(const QString &key, const QVariant &value);
Q_INVOKABLE
QVariant value(const QString &key, const QVariant &defaultValue);
Q_INVOKABLE
bool boolValue(const QString &key, const bool defaultValue);
Q_INVOKABLE
void initToDefaults();
signals:
void settingChanged(const QString& key);
};
#endif // SETTINGS_H
//settings.cpp
#include "settings.h"
Settings::Settings(QObject* parent) :
QSettings(parent) {
}
Settings::~Settings() {
}
QVariant Settings::value(const QString &key, const QVariant &defaultValue = QVariant()) {
return QSettings::value(key, defaultValue);
}
bool Settings::boolValue(const QString &key, bool defaultValue) {
return QSettings::value(key, defaultValue).toBool();
}
void Settings::setValue(const QString &key, const QVariant &value) {
// change the setting and emit a changed signal
// (we are not checking if the value really changed before emitting for simplicity)
QSettings::setValue(key, value);
emit settingChanged(key);
}
void Settings::setValueIfNotSet(const QString &key, const QVariant &value) {
// change the setting and emit a changed signal
if( !QSettings::contains(key) ) {
QSettings::setValue(key, value);
// (we are not checking if the value really changed before emitting for simplicity)
emit settingChanged(key);
}
}
void Settings::initToDefaults() {
setValueIfNotSet("test", true);
}
And in QML i use this class like that:
Button
{
id:button1
nazwa: "Set value"
onClicked: settings.setValue("1","adskmmads")
}
Button
{
id:button2
onClicked: console.log(settings.value("1","error! cannot load data"))
nazwa: "Load value and show"
}
QSettings constuctor needs at least 2 strings organization name and application name
QSettings::QSettings(const QString & organization, const QString & application = QString(), QObject * parent = 0);
In your case just use this code below in your main()
(1)If you use QSettings from many places in your application, you might want to specify the organization name and the application name using QCoreApplication::setOrganizationName() and QCoreApplication::setApplicationName(), and then use the default QSettings constructor:
QCoreApplication::setOrganizationName("MySoft");
QCoreApplication::setOrganizationDomain("mysoft.com");
QCoreApplication::setApplicationName("Star Runner");
...
QSettings settings; //default constructor
(1)reference: QSettings

Using QHash in a custom class

I am newbie in Qt and learning to handle how QHash works. On working with this example I dont understand why this throws me an error. I may miss something, but please guide me to learn this.
main.cpp
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QHash<QString,Person> hash;
QString key="1";
Person p;
p.name = name;
p.number = an;
hash.insert(key,p);
return a.exec();
}
person.h
class Person
{
public:
Person();
Person(QString name,QString num);
bool operator==(const Person & other) const; //== overloading to assign in QHash
QString name,number;
};
person.cpp
Person::Person()
{
}
Person::Person(QString name, QString num)
{
this->name=name;
this->number=num;
}
bool Person::operator==(const Person & other) const
{
bool state;
if (name == other.name )
state = true;
else
state = false;
return state;
}
and the error is:-'qHash':none of the 17 overloads could convert all the argument type.I knw im missing something.Please guide me.
You need the global qHash() function.
A QHash's key type has additional requirements other than being an
assignable data type: it must provide operator==(), and there must
also be a qHash() function in the type's namespace that returns a hash
value for an argument of the key's type.
See this for more info about that.
The code you've provided is not complete and not compilable - e.g. The symbol name is not found, no includes.
The op == is not required when you use the class as value. The only one requirement for value-classes - a default constructor.
I think you problem was something else. If you provided the complete code and the complete list of errors I could tell you what exactly.
Below you'll find the working version of you code-snippet. (For simplicity, everything in one file)
main.cpp
#include <QApplication>
#include <QHash>
#include <QString>
class Person
{
public:
Person(QString name=QString::null,QString num=QString::null);
QString name,number;
};
Person::Person(QString _name, QString _num)
:name(_name),number(_num)
{
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QHash<QString,Person> hash;
QString key="1";
Person p("Orhan Kemal", "1914");
hash.insert(key,p);
return a.exec();
}
Regards,
Valentin
EDIT:
Initialized members not in body