Add functionality to class and all of it's subclasses - c++

I have 3 classes that inherit from 3 different classes which all inherit from QWidget base class.
For example:
MyMainWindow : public QMainWindow : public QWidget
MyPushButton : public QPushButton : public QWidget
MyTextEdit : public QTextEdit : public QWidget
And I will have more classes like this eventually.
What I'd like to do now, is add a common method to all my classes; this means it should be added to the QWidget base class, but I can't edit it (I'd rather not change the Qt source code for one method).
Is this kind of behaviour possible?
I've already tried using interfaces like so:
class MyTextEdit : public QTextEdit, IMyMethodContainer { ... };
But the problem is, I need to access QObject::connect(sender, signal, this, slot); in IMyMethodContainer, and by this I'm trying to access the MyTextEdit, not the IMyMethodContainer, which is not a subclass of QWidget.

CRTP might help.
template<typename Derived, typename Base>
struct InjectMethod: Base {
static_assert( std::is_base_of< InjectMethod<Derived,Base>, Derived >::value, "CRTP violation" );
Derived* self() { return static_cast<Derived*>(this); }
Derived const* self() const { return static_cast<Derived*>(this); }
void my_method() {
// use self() inside this method to access your Derived state
}
};
Then:
class MyTextEdit: InjectMethod< MyTextEdit, QTextEdit > {
};
class MyPushButton: InjectMethod< MyPushButton, QPushButton > {
};
inside InjectMethod< MyTextEdit, QTextEdit > you have access to a self() pointer that has access to all stuff inside MyTextEdit, and inside InjectMethod< MyPushButton, QPushButton > the same.
You may not need the Derived portion -- possibly having a single template parameter (your base) would be enough, if you only use QWidget functionality.

In Java you can "extend" QWidget and add your custom methods there.
Class MyQWidgetExtension extends QWidget { ... }
Your other classes (QMainWindow, QpushButton, QtextEdit) just extend ("inherit") from that. Is there similar for C++?
Class MyQWidgetExtension : public QWidget { ... }

Related

C++ Qt program design issue

In C++ Qt there is a class QWidget
class A inherits QWidget and adds some features
class B inherits A and adds some features
class C inherits B and adds some features, C must be of type QWidget and should do all things done by B
For some reason C is not behaving as expected, I have to rewrite class C. I can not modify code up to class B creation.
How can I solve this problem? Any design pattern, or anything else?
If I try to inherit QWidget and B, a multiple inheritance, there will be two QWidget which leads to problem (QObject - moc does not allow it).
If I inherit from QWidget and pass object of B to C's constructor, whatever operation B performs applies to another QWidget coming through B, which is not desired, all features provided by B should apply to my C's QWidget.
Suppose there is a temperature sensor, when that gets disconnected from machine, class B draws a content blocker image on the whole area of QWidget that it owns, I can monitor sensor connect /disconnect and suppose C's fun. OnDisconnect() gets called, I will call B::OnDisconnect(), B will draw blocker image on its own QWidget, not on the one which is owned by C.
This has everything to do with C++'s rather inflexible method implementation inheritance when compared e.g. to the Common LISP Object System.
Since B's obscuration is always meant to be on top of B's contents, what you effectively need is for B to provide an overlay that draws on top of its contents, even if paintEvent is overriden in derived classes.
See this answer for a simple example, or another answer for an overlay with blur graphical effect.
This is fairly easy to accomplish by having B add an optional overlay widget to itself.
Example:
class OverlayWidget; // from https://stackoverflow.com/a/19367454/1329652
class ObscureOverlay : public OverlayWidget
{
public:
ObscureOverlay(QWidget * parent = {}) : OverlayWidget{parent} {}
protected:
void paintEvent(QPaintEvent *) override {
QPainter p{this};
p.fillRect(rect(), {Qt::black});
}
};
class A : public QWidget {
...
protected:
void paintEvent(QPaintEvent *) override { ... }
};
class B : public A {
...
ObscureOverlay m_obscure{this};
public:
B() {
m_obscure.hide();
}
Q_SLOT void OnDisconnect() {
m_obscure.show();
...
}
};
class C : public B {
...
protected:
void paintEvent(QPaintEvent * event) override {
B::paintEvent(event);
...
}
};
If you don't have the source code to B, you can add the overlay to C, replicating original B's functionality when obscured. All of Qt's slots are effectively virtual, so if you pass a C to someone expecting B and connecting to its OnDisconnect slot, it will be C's slot that will get invoked.
class C : public B {
Q_OBJECT
...
ObscureOverlay m_obscure{this};
public:
explicit C(QWidget * parent = {}) : B{parent} {
m_obscure.hide();
}
Q_SLOT void OnDisconnect() { // slots are effectively virtual
m_obscure.show();
B::OnDisconnect();
}
protected:
void paintEvent(QPaintEvent * event) override {
B::paintEvent(event);
QPainter p{this};
...
}
};

Alternatives to virtual index implementation in a model

So I have again encountered the limits of QObjects that cannot be mixed with templates (at least not directly). Basically I have a proxy model class that uses indexing to translate the source positions to local positions and back. The index can be implemented in number of ways, for now I need two versions, one using QHash and one using QVector. The interface of the index is common to both with only subtle differences regarding index manipulation. With templates this would be easy, I would make the class a template and then used specialization for these two cases.
However the model needs to be a QObject so instead it seems I would need to use polymorphism like so:
class IndexInterface;
class VectorIndex; //inherits IndexInterface
class HashIndex; //inherits IndexInterface
class ProxyModel : public QObject
{
Q_OBJECT
public:
enum IndexType { Vector, Hash };
explicit ProxyModel(IndexType indexType, QObject *parent = 0) :
QObject(parent),
index(indexType == Vector ? new VectorIndex : new HashIndex)
{
}
//...
private:
IndexInterface *index = nullptr;
};
I have couple of issues with this. First, it requires dynamic allocation of the index which I would like to get rid off. Second, because of the use of pointer to IndexInterace to dispatch the calls to the index no method of the index will ever be inlined (I have looked over dissasembled code to confirm this and tried various optimizations etc. to no avail).
What would be the alternatives to this design ideally without dynamic allocation of the index and without virtual calls to the index?
Make the index-type-specific class one of the base classes:
template <typename Index> class IndexHandler {
};
using VectorIndexHandler = IndexHandler<QVector>;
using HashIndexHandler = IndexHandler<QHash>;
class VectorIndexProxy : public QAbstractItemModel, VectorIndexHandler {
... // should be very small
};
class HashIndexProxy : public QAbstractItemModel, HashIndexHandler {
... // should be very small
};
Then instead of passing the index type to the constructor, use a factory function:
QAbstractItemModel * proxyFactory(IndexType indexType, QObject * parent = 0) {
switch (indexType) {
case Foo::Vector:
return new VectorIndexProxy(parent);
...
}
}
If you envision an interface broader or different than QAbstractItemModel, you'll need to write such a base class and derive from it in the concrete implementations, of course.
You could use CRTP if needed for IndexHandler to call directly into the derived class's methods, making it even smaller:
template <typename Index, typename Derived> class IndexHandler {
Derived * derived() { return static_cast<Derived*>(this); }
const Derived * derived() const; // as above
void foo() {
derived()->setObjectName("Yay");
}
};
class VectorIndexProxy :
public QAbstractItemModel,
public VectorIndexHandler<QVector, VectorIndexProxy>
{
... // should be very small
};
You can also "promote" methods from the base class to be Qt slots:
class VectorIndexProxy : ... {
#ifdef Q_MOC_RUN
Q_SLOT void foo();
#endif
};
See this question about having a base non-QObject class with signals and slots.
Finally, you could use the PIMPL idiom, and have a concrete implementation of a fixed type just like you desire. The factory would be invoked in the constructor and you'd be swapping in different PIMPLs for different indices. That's not as expensive as you think since all Qt classes already dynamically allocate a PIMPL, so you can piggy-back on that allocation by deriving your PIMPL from QObjectPrivate (#include <private/qobject_p.h>), and passing the instance of the PIMPL to the protected QObject(QObjectPrivate&). This pattern is omnipresent in Qt, so even though it's an implementation detail, it's not going away in Qt 5 at the very least. Here's a rough sketch:
// ProxyModel.cpp
#include <private/qobject_p.h>
class ProxyModelPrivate : public QObjectPrivate {
// Note: you don't need a q-pointer, QObjectData already provides it
// for you! CAVEAT: q-pointer is not valid until the QObject-derived-class's
// constructor has returned. This would be the case even if you passed
// the q-pointer explicitly, of course.
...
}; // base class
class VectorProxyModelPrivate : public ProxyModelPrivate { ... };
class ProxyModel : public QObject
{
Q_OBJECT
Q_DECLARE_PRIVATE(ProxyModel)
ProxyModel * pimpl(IndexType indexType) {
switch (indexType) {
case Vector: return new VectorProxyModelPrivate();
...
}
public:
enum IndexType { Vector, Hash };
explicit ProxyModel(IndexType indexType, QObject *parent = 0) :
QObject(*pimpl(IndexType), parent)
{}
};
If you were deriving from QAbstractItemModel, your PIMPL would derive from QAbstractItemModelPrivate, in the same fashion; this works for any QObject-deriving class in Qt!

Virtual method misconception in C++

I am not experienced in OOP. I am developing an application using C++ and Qt. I have implemented 2 classes, base one and the one that inherits from it. Then I have added virtual methods for both and everything worked. But then I realized that I don't think it should... Here is the example:
This is my base class :
namespace Ui {
class CGenericProject;
}
class CGenericProject : public QDialog
{
Q_OBJECT
public:
explicit CGenericProject(QWidget *parent = 0);
~CGenericProject();
EMeasures_t type();
private:
Ui::CGenericProject *ui;
virtual void initPlot();
protected:
QCustomPlot* customPlot;
QVector<double> m_x;
QVector<double> m_y;
EMeasures_t m_type;
};
It has a virtual method called initPlot and it looks like this:
void CGenericProject::initPlot()
{
customPlot = ui->workPlot;
customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectAxes );
customPlot->setFocusPolicy(Qt::ClickFocus);
customPlot->xAxis->setAutoTickStep(false);
customPlot->yAxis->setAutoTickStep(false);
customPlot->xAxis->setTickStep(100);
customPlot->yAxis->setTickStep(100);
customPlot->xAxis->setRange(0, 1000);
customPlot->yAxis->setRange(0, 1000);
}
And then i have a class that derives it:
class CEisProject : public CGenericProject
{
public:
CEisProject();
~CEisProject();
private:
virtual void initPlot();
void exampleEisMethod();
};
its initPlot is here:
void CEisProject::initPlot()
{
// give the axes some labels:
customPlot->xAxis->setLabel("Re [Ohm]");
customPlot->yAxis->setLabel("- Im [Ohm]");
customPlot->replot();
}
This is how i create the object:
CGenericProject* test = new CEisProject();
Now, when the initPlot() method is called, first the initPlot() from base class CGenericProject is called and then initPlot() from CEisProject is called. I wanted this functionality, where I can predefine some stuff in generic class and then add specific stuff in the childs.
But when I think of it, shouldn't initPlot() be calles exclusevily? I mean, shouldn't the method be called from base class or child class, instead of both, one after another? I have noticed this after reading this answer.
Constructors:
CGenericProject::CGenericProject(QWidget *parent) :
QDialog(parent),
ui(new Ui::CGenericProject)
{
ui->setupUi(this);
initPlot();
m_x.clear();
m_y.clear();
}
CEisProject::CEisProject()
{
m_type = EMeasures_t::eEIS;
initPlot();
}
You did not show the definition of the constructors, just their declaration. But I'm pretty sure the constructor definitions contain the answer to your question.
You may not be aware that the derived class constructor calls the base class constructor before directing virtual functions to the derived class. So a virtual function called in the base class construction (of an object which will soon be derived class) gets the base class definition of that virtual function.
Also, your constructor should be like:
// File .h
CEisProject(QWidget *parent = 0);
// File .cpp
CEisProject::CEisProject(QWidget *parent) : CGenericProject(parent)
{
...
}
or you won't be able to parent your derived widgets.

Access QList<T> from qml

I want to access a QList from qml.
Here is a sample code
class A;
class B : public QObject {
...
Q_INVOKABLE QQmlListProperty<A> read();
...
private:
QList<A*> lst;
}
I'm using context property to access object of class B in qml.
How can I access the list in qml. Any sample code will be helpful.
You will need to Q_DECLARE_METATYPE(A *) to be able to wrap it in a QVariant for use in QML.
But that's just for referring to and passing it around QML.
If you want to use A in QML as in C++, it will have to inherit QObject and implement properties, slots and such.
You can see how to implement the QQmlListProperty here: http://doc.qt.io/qt-5/qtqml-referenceexamples-properties-example.html
Also, if QObject is too heavy for you and impractical to have a lot of them, you can always use a single QObject derived to work as a controller for a non-QObject but still registered as metatype type.
class A {
public:
int a;
};
Q_DECLARE_METATYPE(A *)
class AProxy : public QObject {
Q_OBJECT
public slots:
int a(QVariant aVar) {
return aVar.value<A *>()->a;
}
void setA(QVariant aVar, int v) {
aVar.value<A *>()->a = v;
}
};
This way you don't have the size overhead and limitations of QObject for every object in the list, and can instead use a single controller to access the data, albeit at lower performance. In your case you could use B to act as both container and controller proxy for A.

Can this be done with multiple inheritance?

Here is what I would like to do.
Say I have Class Widget.
I then create Button from Widget.
I then create ModifiedWidget which re-implements certain functions of Widget.
I then want Button to use ModifiedWidget rather than plain Widget. Is this possible to do some how?
Thanks
class Button : public Widget;
class SuperButton : public Button, public ModifiedWidget;
I'm just not sure if that would do what I want it to though.
The easiest way is to use encapsulation, not inheritance.
class Button
{
Button(Widget * w) { mywidget = w; }
Widget * mywidget;
};
Another way is to let Button be a template class.
template<class Parent>
class Button : Parent
{
};
Button<Widget> mybutton1;
Button<ModifiedWidget> mybutton2;
Keep them separate:
class Widget {
...
virtual void some_function();
};
class ModifiedWidget : public Widget {
...
// override the base version of this method
virtual void some_function();
};
class Button {
Button(Widget* w) : widge(w) { }
Widget* widge;
};
class SuperButton : public virtual Button {
SuperButton(Widget* w) : Button(w) { }
};
Now your Widgets have a hierarchy, and your Buttons have their own hierarchy. And it probably makes more sense to say that your Button contains a Widget, than to say that your Button is a Widget. Thus, we go with encapsulation instead of inheritance for the Button-Widget relationship, but still have inheritance for the Buttons and Widgets separately.
If I have understood your question, this is typical Dreaded Diamond Problem
With some care, it is possible, although I suggest reconsidering your design, because multiple inheritance can be often avoided (which brings simpler and cleaner design).
Also Read C++ Faq on Dreaded Diamond
In reply to your example, you will have to use virtual inheritance for Button and ModifiedWidget classes.
class Button : public virtual Widget;
class ModifiedWidget : public virtual Widget;