Approaches to creating the View for "Humble Dialogs" - c++

I have a bunch of questions to post regarding the issue of separating the view from logic when creating a GUI.
The following is a minimal example of what I would do for a simple dialog that has a label and a button using the "Humble Dialog" approach. Pressing the button should show some text on the label. I have used C++ an Qt that I am comfortable with but I guess it is readable by all other audiences.
In any case I am interested in possible side effects because of the choice of language (I am using C++ in the project I am interested in introducing this).
class IView {
public:
IView(){}
virtual ~IView(){}
virtual void showResult(const QString &text)=0;
};
class Presenter {
public:
Presenter(IView *view){
m_View = view;
}
~Presenter(){}
void buttonPressed(){
QString text;
// Evaluate text
m_View->showResult(text);
}
private:
IView *m_View;
}
// Multiple inheritance. Is this OK?
class MyView : public QDialog, public IView {
public:
MyView(){
m_Presenter = new Presenter(this);
m_Button = new QPushbutton(this);
m_Label = new QLabel(this);
// Ui event handled inside view but then directly
// propagated to the Presenter
connect(m_Button,SIGNAL(clicked()),this,SLOT(buttonPressed()));
}
~MyView(){
delete m_Presenter;
// Qt will automatically delete m_Button and m_Label;
}
void showResult(const QString &text){
m_Label->setText(text);
}
protected slots:
void buttonPressed(){
m_Presenter->buttonPressed();
}
private:
Presenter *m_Presenter;
QPushbutton *m_Button;
QLabel *m_Label;
}
class TestView : public IView {
public:
TestView(){}
~TestView(){}
void showResult(const QString &text){
m_LabelText = text;
}
QString getResult(){
return m_LabelText;
}
private:
QString m_LabelText;
}
// Test code
TestView view;
Presenter presenter(&view);
presenter.buttonPressed();
EXPECT_EQ(view.getResult(),"Expected Result");
// Procuction code
MyView view;
view.show();
Now this is what I got by following the initial work on the Humble dialog by Feathers. The approach that I would get from Fowler's implentation would be to avoid creating the instance of the Presenter class in the constructor of MyView but pass it as a parameter instead so the production code would look like the test code. I personally like the approach I present here.
So,
Is it meant to be used with multiple inheritance (see my comment in MyView class)?
Should the events be propagated directly to the Presenter or should they be handled in the view that will call the respective presenter action (as I have done here to avoid having to make the Presenter a QObject so it can handle UI events)?
Are there any other remarks?

When you do multiple inheritance with QObjects, the first class in the inheritance list needs to be the QObject-derived class. This is only strictly required if you plan to add signals and slots to your class, but is good practice anyway. So your class declaration:
class MyView : public IView , public QDialog {
needs to become this instead:
class MyView : public QDialog , public IView {
Again, this will only bite you if you ever add a slot or signal to "MyView".
Other than that, I think this is a fine implementation, albeit huge amounts of overkill for a dialog. :)
I'm using Fowler's MVP with Qt, and it's working okay. Things are more testable (nUnit style), but it is a bit more complex IMO.

I usually use the same pattern for my UI in C# Winforms stuff.
You're actually not really doing multiple inheritance here. One of the classes you're inheriting from is just an empty interface. The only problem here is that C++ doesn't know the difference between a class and an interface.
I don't think there's a problem with creating the presenter inside the view like this either. It's not the most testable design but you're probably not going test the view anyway because there's nothing to test there if you're using humble dialog. Or you could do "poor man's DI" by adding a second constructor that injects a presenter instead of creating it for testing purposes.
In C# I usually have views that don't know about the presenter at all and just throw events instead of calling the presenter. This adds some decoupling but might be overkill in most situations.
Overall this is a good implementation. If I'll ever have to write a C++ app with a UI i'm going to check this post

Looks OK to me. But I would not use QString in the IView-Interface. Use some presentation independend type, if possible. That way, you can change the GUI-toolkit, without affecting the program logic and tests. Keep QString only if it is really painful to convert between QString and std::string or char* (I have no idea...).

Related

How to restrict access to the most direct base class, while still exposing the base-base classes?

I have a class hierarchy similar to this:
class Widget {
// a lot of virtual members
};
class Button : public Widget {
// new stuff + overrides
};
class MySuperButton : public Button {
// ...
};
And I would like to hide the fact that MySuperButton inherit from Button, but not from Widget. Basically making the inheritance from Button private while keeping all its base classes public.
Why?
I have a complicated widget build on Button, which needs to maintain some invariant with its button state. Exposing it has a Button might allow something to
modify the button directly breaking these invariants.
Example:
MySuperButton button;
button.setText("Click me!") // calls Button::setText
// Oh no, MySuperButton set some special text which has now been overriden =(
What doesn't work
Making MySuperButton inherit from Button privately also hides Widget, preventing me from doing Widget things with my button.
Using access specifiers does not prevent MySuperButton to be converted into a Button.
So void doButtonStuff(Button& b); will accept a MySuperButton& just fine.
Using compositon forces me to reimplement a bunch of stuff that Button already reinmplements, just to forward it which is a PITA. Especially since the actual hierarchy is rather deep and these are big classes.
Virtual inheritance doesn't seem to work as the base isn't visible (not sure why that would be a problem though). See Godbolt
I can not modify the Button or Widget classes as they are from an external library (Qt in this case). Also the actual code is somewhat more complicated, the provided hierarchy is for illustration.
Is there any way to do this, or do I need to accept that my widget can be broken if I am not careful ?
What you are asking is not really possible.
A possible Qt-specific solution is the following:
class MySuperButton : public Widget {
public:
MySuperButton () {
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(button = new Button());
setLayout(layout);
}
private:
Button *button;
}

Qt object management with Qt Plugins

My question is how to do proper object/resource management when working with Qt plugins. Default RAII does not seem to work well with Qt.
In our application we work with modules (Qt plugins) that are dynamically loaded at runtime. When loaded plugins can initialize themselves and as part of this initialization phase they can add their own widgets to the application.
- to the toolbar
- to a side panel
- etc.
Widgets that are added to the main windows have their ownership also transferred.
This all works fine, but now that our application grows more complicated we also need to pay attention to the shutdown phase. Simply unloading the modules will get us into all kinds of trouble. Objects that aren't there or types that are unloaded while their objects are still alive.
To have a reliable shutdown it seems that the only proper way to go is to do reverse initialization. This also means that every module that adds widgets to the mainwindow must remove them as well. Already trying to do this with the first widgets got me into trouble.
Module A registers widget W with the MainWindow. Preferably I would want to return a scoped object removing and deleting the widget when going out of scope. However already it seems that given widget W you cannot remove it simply from the toolbar as it works with actions (and removing the action does not delete the widget! See example below).
Concluding, it seems to me Qt is made in such a way that it gets ownership of everything and you have to rely on Qt to delete it. This does not work well with modules. I'm looking for a solution/best practice here.
Edit:
I added an example where a module adds a custom widget to the toolbar of the MainWindow. My goal is that the module is in charge of when the widget is deleted, for the reasons stated before. The example is to make the question more concrete. It represents the generic problem - ownership of qt objects - that use this pattern in combination with plugins.
example:
executable.cpp
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0) {
ui->setupUi(this);
LoadPlugin();
}
void LoadPlugin() {
m_plugin = new QPluginLoader("module.dll");
m_plugin->load();
IModule* moduleInstance = qobject_cast<IModule*>(m_plugin->instance());
moduleInstance->Initialize(this);
}
void AddToolbarSection(QWidget* widget) {
/** ownership is transferred here to Qt */
mainToolBar->insertWidget(pWidget);
}
void RemoveToolbarSection(){
/** How to get the widget deleted? */
}
/** this is called before the destructor */
void UnloadPlugin() {
moduleInstance->Shutdown();
m_plugin->unload();
}
~MainWindow() {
/** deletion of toolbar sections must already been done here
as the modules are already unloaded. Otherwise access violations occur
because specific type information is not accessible anymore.
*/
}
private:
Ui::MainWindow *ui;
QPluginLoader* m_plugin;
IModule* m_moduleInstance;
};
module.cpp
class EXPORT_MODULE IModule : public QObject
{
Q_OBJECT
Q_PLUGIN_METADATA(IID IModuleIID)
Q_INTERFACES(IModule)
public:
IModule() {
}
void Initialize(QMainWindow* window) {
/** QMyToolbarSectionWidget is a custom widget defined in this module (module.dll)
it has a specific destructor and triggers all kinds application
specific cleanup */
m_toolbarSection = new QMyToolbarSectionWidget();
window->AddToolbarSection(m_toolbarSection);
}
void Shutdown() {
window->RemoveToolbarSection(m_toolbarSection);
}
private:
QWidget* m_toolbarSection;
};
That's a bit difficult to answer since it depends on your architecture.
In general Qt's idea of cleanup is tied to the parent pointer. i.e
QObject *root;
QObject *leaf = new QObject();
leaf->setParent(root);
root->deleteLater();
QPluginLoader will even cleanup your root component on unload, so in theory, any tree below your plugin is cleared. Simply make sure that everything you return from your root is a QObject parented to your root. If it's not a QObject, wrap it in QObject.
class MyExtension : public QWidget {
QAction *myAction;
MyExtension() : QWidget() {
myAction = new QAction(this);
}
QAction *getAction() {
return myAction
}
}
from your question i understand you might also be working like this:
class MyExtension : public QObject {
MyWindow * myWindow;
QAction * myAction;
MyExtension() : QObject() {
myWindow = new MyWindow(this);
myAction = new QAction(this);
}
void addToMainThing(TheMainThing *tmt) {
tmt->addWidget(myAction);
}
}
same thing. simply always make sure your QObject is parented to something that is parented to your plugin root.
Cross posting this question on the Qt forum got me the following answer.
Even though Qt takes ownership of QWidgets/QObjects that are added to the Ui, it is still possible to delete them from the client side. Qts resource management system is built in such a way that it will know when a QObject gets deleted and it will handle this deletion by updating the UI as well as removing internal references to it. See the link for more details.

Qt Extending my own widget

To put it simply, I want a new class that extends a custom widget that I've made, and thus have full access to it's UI.
I've tried several different methods so far based on how one would normally subclass/extend classes, but I'm somehow failing horribly for so many different reasons.
Additionally, simply using my widget as a member in my new class wouldn't do for this situation.
Can someone illustrate a quick example of how I would do this? I have done a bunch of searching but I can't seem to find any hits relating to exactly what I'm trying to do
If all else fails I will simply copy over the code and make an actual new widget, which technically would have saved me lots time, but it just doesn't feel right doing that.
My first instinct was to do something like this ( Qwe being my new class, Asd being the widget ):
class Qwe : Asd {public: ...}
And I even made the widget's Ui public, but then I just got the error :
use of undefine type Ui::Asd
whenever I tried to access the Ui's elements.
Let's say we have a custom widget named BaseWidget and a child widget named ChildWidget. Declare BaseWidget as usually, but make its ui member protected instead of private, like this:
protected:
Ui::BaseWidget *ui;
Declare ChildWidget as an ordinary widget derived from BaseWidget. Make sure you include ui_BaseWidget.h in the ChildWidget.cpp file, just as you do it in BaseWidget.cpp (this include and the header itself is generated by Qt).
Header:
#include "BaseWidget.h"
class ChildWidget : public BaseWidget {
Q_OBJECT
public:
explicit ChildWidget(QString text, QWidget *parent = 0);
};
Source:
#include "ChildWidget.h"
#include "ui_BaseWidget.h"
ChildWidget::ChildWidget(QString text, QWidget *parent) :
BaseWidget(parent)
{
ui->label->setText(text);
}

Promoting code reuse for this situation

This is a bit tricky to explain but I will try my best to explain it.
I'm making a Gui API for games and it has Themes.
First I'll explain how Widgets work.
A Button for example, inherits from Widget.
Themes work similarly.
ButtonTheme inherits from WidgetTheme.
Inside each widget class, there is an instance of its corrosponding Theme.
Widget class has:
private:
static WidgetTheme widgetTheme;
public:
static WidgetTheme& getWidgetTheme();
button class has:
private:
static ButtonTheme buttonTheme;
public:
static ButtonTheme& getButtonTheme();
the Widget constructor, builds itself from its theme ex:
Widget()
{
setFont(getWidgetTheme().getFont());
}
the Button, inheriting from WidgetTheme, has to do the same ones because the internal widget will not know to construct from ButtonTheme, so my button ends up having to do:
Button()
{
setFont(getButtonTheme().getFont());
setButtonPadding(getButtonTheme().getButtonPadding());
}
This is where my problem is. It really feels wrong that I have to reprovide all the WidgetTheme ones and redirect them to ButtonTheme's parameters for Widget. If I do not do this, a SuperButton would inherit the styles of Button which would also inherit the styles of Widget, but what I want is for SuperButton to use its version of ButtonTheme and WidgetTheme because SuperButtonTheme would inherit from ButtonTheme and WidgetTheme.
Is there a way I could redesign this so that the constructor only has to set parts of the theme that it brings, and not have to set those of its parents?
Thanks
A virtual getTheme() (as drewish suggests) but using covariant return types ought to solve your problem without requiring casts.
The Widget constructor can accept a WidgetTheme and use that.
Widget(const WidgetTheme& theme)
{
setFont(theme.getFont());
}
Button() : Widget(getButtonTheme())
{
setButtonPadding(getButtonTheme().getButtonPadding());
}
I'm not quite clear on where getButtonTheme() and getWidgetTheme() live in your object hierarchy but it seems like it should be up to the class to know what its theme is so why not have a getTheme() method on your class? Maybe I'm too used to scripting languages and not appreciating some issues with strict typing.

qt GUI connecting

I am just starting out with QT. I have read through some tutorials, and I think I have an understanding of signals and slots. I am writing a GUI that has various buttons that change the state of my main program. So for example in a drawing app, you would pick different drawing tools (using various buttons).
What is the best way to go about this? My first thought was to try to connect the clicked signal of the PushButton to some function that sets a current_tool variable. I did some searching and couldn't find a way to connect a QObject signal to a regular function.
This leads me to believe that there is probably a different approach. One where I create a new QObject (my own extension that is) that has various GUI properties. I would then define my slots here for the various buttons.
What is the best way to do this in QT. I am new and do not know of the preferred practice.
Any info would be useful,
thanks
You can define these "normal functions" as slots. Slots are just normal functions that can also be called by signals:
class ToolSelector : public QObject {
Q_OBJECT
public:
Tool *selected;
public slots:
void selectBrush();
void selectPen();
void selectFill();
};
ToolSelector::selectBrush() {
delete selected;
selected = new Brush();
}
ToolSelector::selectPen() {
// ...
}
// ...
toolsel = new ToolSelector();
brushButton = new QPushButton();
connect(brushButton, SIGNAL(clicked()), toolsel, SLOT(selectBrush()));
Inherit from the class that uic generates, creating, say, a MyAppWindow class. Provide extra METHODs in that class, as well as a Document or Drawing object. Connect these methods to the signals you're interested in, and them alter a member variable that contains the drawing state.