How to use enum in Qt? - c++

I have a QObject class Message and another one named Request that inherits the message class. Here's the header file:
#ifndef MESSAGE_H
#define MESSAGE_H
#include <QObject>
class Message : public QObject
{
Q_OBJECT
public:
explicit Message(QObject *parent = 0);
QString Source;
QString Destination;
QString Transaction;
QList<QObject> Content;
signals:
public slots:
};
class Request : public Message
{
Q_OBJECT
Q_ENUMS(RequestTypes)
public:
explicit Request();
enum RequestTypes
{
SetData,
GetData
};
RequestTypes Type;
QString Id;
};
#endif // MESSAGE_H
Now I want to create a Request in my code and set Type to SetData. How can I do that? Here's my current code which gives the error "'Request::RequestTypes' is not a class or namespace". The header file from above is included in my main programs header file, so Request is known and can be created and I can set the other properties - but not the Type:
Request *r = new Request();
r->Source = "My Source";
r->Destination = "My Destination";
r->Type = Request::RequestTypes::SetData;
In other words: I could as well had taken a QString for the Type property of a Request, but it would be nice and safer to do this with an enum. Can someone please show me what's wrong here?

You need to declare the enum like so:
enum class RequestTypes
{
SetData,
GetData
};
in order to use it like you did, but that requires C++11.
The normal usage would be (in your case):
r->Type = RequestTypes::SetData;

Yo can use like this;
typedef enum
{
SetData,
GetData
}RequestTypes;

Related

Qt Quick: QML/C++ expression cannot be used as function?

could you take a look and explain, what am I doing wrong in code below?
#ifndef BACKEND_H
#define BACKEND_H
#include <QObject>
#include <QDebug>
#include <QtQml>
class BackEnd : public QObject
{
Q_OBJECT
Q_PROPERTY(int player READ player WRITE player_change)
QML_ELEMENT
int player;
public:
explicit BackEnd(QObject *parent = nullptr);
signals:
int player_changed(int player);
public slots:
int player_change(int player);
};
#endif // BACKEND_H
cpp:
#include "backend.h"
BackEnd::BackEnd(QObject *parent)
: QObject{parent}
{
}
int BackEnd::player_change(int player)
{
return (player == 1) ? 2 : 1;
}
Error:
Expression cannot be used as a function
Error appears in auto-edited moc file...
Removing Q_PROPERTY makes it fine...
The error says that the Q_PROPERTY macro can't use the member player as a function.
A READ accessor function is required if no MEMBER variable was
specified. It is for reading the property value. Ideally, a const
function is used for this purpose, and it must return either the
property's type or a const reference to that type. e.g.,
QWidget::focus is a read-only property with READ function,
QWidget::hasFocus().
You need to create a getter and use it as the READ function. Or you use MEMBER.
A MEMBER variable association is required if no READ accessor function
is specified. This makes the given member variable readable and
writable without the need of creating READ and WRITE accessor
functions. It's still possible to use READ or WRITE accessor functions
in addition to MEMBER variable association (but not both), if you need
to control the variable access.
Have a look here.
#ifndef BACKEND_H
#define BACKEND_H
#include <QDebug>
#include <QObject>
#include <QtQml>
class BackEnd : public QObject
{
Q_OBJECT
Q_PROPERTY(int foo READ foo WRITE setFoo NOTIFY fooChanged)
Q_PROPERTY(int bar MEMBER bar NOTIFY barChanged)
QML_ELEMENT
public:
explicit BackEnd(QObject *parent = nullptr) : QObject{parent} {}
int foo() const { return m_foo; }
void setFoo(int val) { m_foo = val; emit fooChanged(); }
signals:
void fooChanged();
void barChanged();
private:
int m_foo;
int bar;
};
#endif // BACKEND_H

Qt plugin: Unable to get enum's metadata from a Qt plugin

I can access a lot of metadata from my Qt plugin, but I cannot access the enumerations as QMetaEnums. I am however able to get the method in my class which returns that enum, and am able to convert it to QMetaType and get its id (1026). I need the info contained in QMetaEnum too. I think I am missing something. Please take a look at my code:
//Plugin interface
class PluginInterface
{
public:
virtual void initialize() = 0;
};
#define PluginInterface_iid "pluginInterface"
Q_DECLARE_INTERFACE(PluginInterface, PluginInterface_iid)
//Actual plugin implementing PluginInterface
enum Fruit{ Apple, Pear, Mango };
Q_DECLARE_METATYPE(Fruit)
class MYQTCALCPLUGINSHARED_EXPORT MyQtCalcPlugin : public QObject, PluginInterface
{
Q_CLASSINFO("version", "0.1")
Q_OBJECT
Q_PLUGIN_METADATA(IID PluginInterface_iid FILE "myqtcalcplug.json")
Q_INTERFACES(PluginInterface)
Q_ENUMS(Fruit)
public:
explicit MyQtCalcPlugin(QObject *parent = 0);
void MyQtCalcPlugin::initialize()
{
qRegisterMetaType<MyQtCalcPlugin*>("MyQtCalcPluginPtr");
qRegisterMetaType<Fruit>("Fruit");
qRegisterMetaType<Fruit*>("FruitPtr");
}
public slots:
Fruit TasteFruit()
{
return Fruit::Apple;
}
};
#endif // MYQTCALCPLUGIN_H
//application that is reading the metadata
QPluginLoader pluginLoader(pluginPath);
if (pluginLoader.load());
QObject *pluginInstance = pluginLoader.instance();
auto pluginInterface = qobject_cast<PluginInterface*>(pluginInstance);
pluginInterface->initialize();
const QMetaObject *pMetaObject = pluginInstance->metaObject();
int count = pMetaObject->enumeratorCount(); //count becomes 0
Enum has been moved from outside of the class to inside of it. This fixed the issue. Q_DECLARE_META_TYPE(Fruit) and qRegisterMetaType were redundant:
#define PluginInterface_iid "pluginInterface"
Q_DECLARE_INTERFACE(PluginInterface, PluginInterface_iid)
//Actual plugin implementing PluginInterface
class MYQTCALCPLUGINSHARED_EXPORT MyQtCalcPlugin : public QObject, PluginInterface
{
Q_CLASSINFO("version", "0.1")
Q_OBJECT
Q_PLUGIN_METADATA(IID PluginInterface_iid FILE "myqtcalcplug.json")
Q_INTERFACES(PluginInterface)
Q_ENUMS(Fruit)
public:
enum Fruit
{
Apple,
Pear,
Mango
};
}

How to access a struct from another another C++ class?

Hello I have a struct in a TreeItem class:
// TreeItem.h
class TreeItem
{
public:
struct TreePair
{
QString sa_key;
QVariant sa_value;
};
//... blabla
}
I would like access that struct TreePair from another class TreeModel , which has class TreeItem already formarded in its header:
// TreeModel.h
class TreeItem;
class TreeModel : public QAbstractItemModel
{
Q_OBJECT
//..
}
// TreeModel.cpp
TreeModel::TreeModel(const QStringList &headers, const QString &data, QObject *parent)
: QAbstractItemModel(parent)
{
QVector<TreePair> rootData; // TreePair was not declared in this scope
}
My strcut was not declared in this scope?? In every class it was already automatically set like
#ifndef _TREEITEM_H
#define _TREEITEM_H
#endif
Since TreePair is nested inside TreeItem, it needs to be
QVector<TreeItem::TreePair> rootData;

Subclassing QString to add more functionality?

Trying to add functionality to QString but get build errors ?? And if I am missing things??
#ifndef CSTRING_H
#define CSTRING_H
#include <QString>
#include <QStringList>
#include <QObject>
class CString : public QString, public QObject
{
Q_OBJECT
public:
explicit CString(QObject *parent = 0);
QStringList Find(QString qstrSearch);//all occurances
signals:
public slots:
};
#endif // CSTRING_H
#include "cstring.h"
CString::CString(QObject *parent) :
QString(parent) //ERROR IS POINTING TO HERE
{
}
QStringList Find(QString qstrSearch)//all occurances
{//indexOf, contains
QStringList qstrList;
return qstrList;
}
Don't derive classes form QString since it wasn't designed with polymorphy in mind (note that it has no virtual methods, in particular no virtual destructors) If you want to provide new utility functions, just use free functions - you may want to put them in a namespace:
namespace CString {
QStringList find(const QString &search);
}
QString(parent) Qstring does not have a constructor taking a QObject-parent as parameter. Therefor the compiler tries to cast your QObject to closest Matching constructor, which probably would be QString ( QChar ch )
You should use composition instead of inheritance here, because QString is not designed for subclassing. You can get a lot of troubles if you will subclass it.
Do something like this:
class CString : public QObject //if you're really need this class to be QObject, that's not always a good idea
{
Q_OBJECT
public:
explicit CString(QObject *parent = 0) :
QObject(parent),
mString() //QString have no constructors with parameter QObject*...
{
}
private:
QString mString;
}
Of course, implementation should be in cpp file, it's just a short example

c++ destructors

consider this scenario:
I need to create a ui for some settings. As, data and ui should be separated in theory, I defined a separate class which takes care of the configuration data. The question I have is how to instantiate the data class inside the settings class.
One way is to create the data class in the caller object, I mean the object that calls the settings menu class.
The other way, which my question is involved with, is to create a DATA class variable inside the settings class. I doubt what happens when the settings class gets destroyed then! would the data class object inside settings class also get destroyed? what about if it is defined as a static member of settings class?
#ifndef SETTINGSWINDOW_H
#define SETTINGSWINDOW_H
#include <QMainWindow>
#include <QModelIndex>
#include <QSignalMapper>
#include <QRadioButton>
#include <QSpinBox>
#include <QTimer>
#include "cameracommands.h"
struct Config
{
/* General Options */
QString general_key_lock;
QString general_back_light;
};
//class IConfigSource
//{
//public:
// virtual Config config() const;
// virtual void setConfig(const Config& cfg);
//};
class ConfigSource /* : public IConfigSource*/
{
public:
ConfigSource() {
config_.general_back_light = "OFF";
config_.general_key_lock = "OFF";
}
Config config() const {return config_;}
void setConfig(const Config& cfg) {config_ = cfg;}
private:
Config config_;
};
class ConfigUpdater : public QObject
{
Q_OBJECT
public:
ConfigUpdater(ConfigSource& src) : src_(src) {}
public slots:
void apply () {src_.setConfig(tempConfig_);}
void cancel() {tempConfig_ = src_.config();}
public:
void updateGeneralBackLight(QString s) {tempConfig_.general_back_light = s; qDebug() << "BackLight updated :)";}
void updateGeneralKeyLock(QString s) {tempConfig_.general_key_lock = s; qDebug() << "KeyLock updated :)";}
Config tempConfig_;
ConfigSource& src_;
};
//----------------------------
namespace Ui {
class SettingsWindow;
}
class SettingsWindow : public QMainWindow
{
Q_OBJECT
public:
explicit SettingsWindow(QWidget *parent = 0);
~SettingsWindow();
signals:
void clicked(const QString &text);
void sendToPLC(QByteArray );
public slots:
void updateGeneralBackLight();
void updateGeneralKeyLock();
void getRow(QModelIndex);
void MySlot(QString);
private slots:
void on_pushButton_5_clicked();
void on_pushButton_3_clicked();
private:
void set_mappings();
Ui::SettingsWindow *ui;
ConfigUpdater *config_updater;
QSignalMapper *mapper;
};
#endif // SETTINGSWINDOW_H
and this is the source:
QMainWindow(parent),
ui(new Ui::SettingsWindow)
{
/* initializations */
ui->setupUi(this);
ConfigSource src;
config_updater = new ConfigUpdater(src);
That depends on how do you need to use it.
Scenario 1. The settings need to be held in memory when the program is working.
Scenario 2. The settings need to be saved to the disc immediately, and then will be read on-demand.
In scenario 1, you need to be able to always access the data in the memory. So it is better to separate the settingsUI class and the settingsData class, so you will have access to the latter.
class settingsUI
{
<...>
private:
settingsData * data;//pointer to the data object
}
class settingsData
{
}
In scenario 2, you can aggregate settingsData into the settingsUI, and save the data to a file when the UI is destroyed.
class settingsUI
{
public:
<...>
~settingsUI();
private:
class settingsData
{
<..>
}data;
<...>
}
class settingsUI::~settingsUI()
{
data.saveToFile();
}
And yes, uf you aggregate settings into the UI, it will be destroyed when the UI is destroyed. Holding data as a static member is not the best idea, it is better to separate the data from the visual representation (which is in your case the UI class).
UPD:
If you want to hold it just until the program exits, I would suggest you to hold a static pointer to the data in the UI class. Here is an example with raw pointers, but you can use smart pointers too, ofc.
class data
{
}
class UI
{
private:
static data * data_;
}
data* UI::data_;
When your program starts, allocate memory for the data: UI::data_ = new data(), and when your program ends (or if you don't need the data anymore), free the memory: delete UI::data_. Once again, it is better to use smart pointers, so this is just an example.
If the settings class is used by only the UI then it makes sense to keep it within the UI class:
class Settings {
int a;
int b;
};
class Ui {
private:
Settings settings;
};
settings will be destroyed during the destruction of Ui.
If you are using the Settings object in many places, it makes more sense to keep a shared pointer to it:
class Ui {
public:
Ui(std::shared_ptr<Settings> someSettings)
: settings(someSettings)
{}
private:
std::shared_ptr<Settings> settings;
};
This Settings object will be destroyed when the last owner of the shared_ptr is destroyed.
Yes the data object would get destroyed when the settings object is destroyed. If you make it a static member then it would not. But that's probably not such a good idea. A better way would be to persist the data object to a file (say). You can read the file in the settings object constructor and write the file in the settings object destructor.
EDIT
class SettingsWindow : public QMainWindow
{
Q_OBJECT
public:
explicit SettingsWindow(ConfigSource& src , QWidget *parent = 0);
...
}
SettingsWindow::SettingsWindow(ConfigSource& src , QWidget *parent)
QMainWindow(parent),
ui(new Ui::SettingsWindow)
{
ui->setupUi(this);
config_updater = new ConfigUpdater(src);
...
}
thanks, it is correct. The program terminates when I attempt to pass the below variable to the user-defined function:
(inside header)
void print_config(Config cfg);
Ui::SettingsWindow *ui;
ConfigUpdater *config_updater;
inside cpp:
void SettingsWindow::print_config(Config config)
{
qDebug() << config.general_back_light;
qDebug() << config.general_key_lock;
}
void SettingsWindow::on_sendToMainButton_clicked() /* cancel */
{
print_config(config_updater->tempConfig_);
print_config(config_updater->src_.config());
}
the first, print_config instruciton works fine, as for tempConfig_, but the when I pass src_ in the second statement, it jump outta program.
//------------
I know where the problem comes from, but I cannot solve it, i hope this can help:
class ConfigUpdater : public QObject
{
Q_OBJECT
public:
ConfigUpdater(ConfigSource& src) : src_(src) {}
public slots:
void apply () {src_.setConfig(tempConfig_);}
void cancel() {tempConfig_ = src_.config();}
public:
Config tempConfig_;
ConfigSource& src_;
};
Here, src_ is passed by reference, everywhere, even in the constructor of Settings window.
the program fails when I attemp to access it inside memory, for example:
config_updater->cancel();
which does:
void cancel() {tempConfig_ = src_.config();}