Unable to understand Undo Redo Framework in Qt - c++

I am learning to use Qt for my application development & I am pretty successfull in developing my Application. Now I want to implement Undo Redo Functionality for my Application. The doc for this topic has little information. I have even tried understanding from the 2 examples in the SDK. But I am having a tough time understanding how it works.
Can somebody please take the trouble of explaining me how to implement it?
There are various state's in my application for which I want to provide this functionality.
So can the explaination be from the general point of view?
If there are already articles on the internet explaining the same then please notify me about them. That would be very helpful.
Thank You.

There are 2 core classes: QUndoCommand and QUndoStack;
QUndoCommand is the base class of your command class. You have to implement undo() and redo() yourself.
QUndoStack is basically a container of QUndoCommand objects, with extra methods like creating QAction, query undo/redo text of current QUndoCommand(Simple functionalities which you can implemented yourself easily)
What you need to do is:
Implement your commands. You need to decide how to implement redo/undo yourself according to your need. class AppendText is a good example: http://qt-project.org/doc/qt-5.0/qtwidgets/qundocommand.html
Keep a QUndoStack instance for each document(Or one instance if there is only one document in the application).
Say you have an "AppendText" command class, and an "Append" button in the UI. If "Append" button is clicked, you need to create an AppendText command instance, and call QUndoStack::push(appendCmd). QUndoStack::push() will call AppendText::redo() first, and then put it into the container for undo.
That's it.

Related

c++ application save and apply preference pattern (may be boost or something)

Typical situation: you have an application, that save and load preferences
(save and load handled by class Config).
Imagine there's such a preference for fonts of some GUI elements.
So we have
struct Font;
struct Config {
const Font& getFontForSpecificGUIElement() const;
//save to disk if Font changed
void setFontForSpecificGUIElement(Font);
};
Whenever the font is changed I need to inform all instances of class SpecificGUIElement of that change.
How can achieve such notification functionality?
To keep Config simple I want to decouple that functionality. Besides, there will many properties like this (30-50 of them).
So in general I want:
Not require implementing virtual interfaces
I don't need thread safety
Convenient registration of event handlers
I need notification for new subscribed receivers, with last recent
notification if were any (I mean, as in my example Font changed, and when new GUI elements subscribe on such event, they receive, event automatically triggered for them, and they receive last variant of Font)
Convenient registration of event type (I mean in item above
we create some kind of value cache, so it should be simple add new one)
I suppose this is common enough requirements, so may be there already solution,
in popular C++ libraries, like boost ?
Update:
Why Qt not suitable for me. I see two approaches
with Qt, QEvent subsystem. But because of it is impossible
send event to unknown listeners it is no go. Why not signal/slots, first you need inherit QObject, second to implement (4), I have to create MessageBus class to cache last values, and adding new events starts require to much work:
add data field, add new signal, add function(X) to emit new signal, because of signal actually protected functions,
plus in (X) i need compare last value with new one.
Yes, this alsready exists in e.g.:
Boost Signals2
http://www.boost.org/doc/libs/1_59_0/doc/html/signals2.html
There are many samples that should get you going.
Signals2 does offer thread safety, but I guess that doesn't harm.
Alternatively,
Qt
Qt does have a signals/slots implementation, as do many other UI frameworks:
http://doc.qt.io/qt-4.8/signalsandslots.html

Dynamical overriding

I want to dynamically instantiate a QWidget and bind its "Pressed" event, either with a Qt signal or by overriding a function.
However I'm only allowed to create one new .cpp file.
I don't know how to override a C++ function dynamically, or how to change a virtual function into a Qt signal.
Is what is represented in the picture above achievable ?
The Widgets Tutorial of the Qt docs is a nice starting point.
Under Qt Widgets Examples you can find the Calculator Example, which should contain all of what you want to do.
Take the code, strip it down to what you need, use and try to understand it.
Or maybe have a look at the Getting Started section.

How to save layout settings of MFC application?

I understand there are functions that can easily write windows registry, however I found out that in new MFC project created with wizard, some information (like split bar position, visibility of controls) gets stored automatically (or at least I found no CWinApp::Write* calls in the project). Since I have also older projects that don't have this behaviour I need to figure out how to make this without help of project wizard. Would anyone please know how does this work?
The MFC control state saving magic happens in the 'New' MFC Feature Pack, specifically in the SaveState methods, for example CMFCToolBar::SaveState.
To take advantage of this you'll therefore need to upgrade your Toolbars and Menus to use the newer controls and upgrade your application to inherit from CWinAppEx. I recommend that you use a New MFC Wizard based app as a guide on how to upgrade your old MFC app.
Most of the information is saved in CPane::SaveState(), thus if you want state of some component saved, you need to use classes derived from CPane. (for more info here is the class hierarchy).
The process of saving window states is initiated through CFrameImpl::OnClosingMainFrame(). This function in turn calls CWinAppEx::SaveState() which saves some application settings and then ALL instances of CMFCToolBar (they add themselves to global list of CMFCToolBars in call to OnCreate). In a similar way all dockable panes are saved but the list belongs to your main frame. Then positioin and size of your main frame is saved.
CViews and CFrameWnds are somewhat less favored, for what I found and tried out, the only information saved was visibility.
I used that loooong time ago. If I correctly reminds it, you should save the informations you want in a overridden CWinApp::ExitInstance() before calling base class method, and you load them in CWinApp::InitInstance. Be sure to allow for default values, because at first run, there will be nothing to load, and do not forget to call (or copy) base class.

How do you programatically update the UI in Qt?

I'm fairly new to Qt, and am trying to wrap my head around signals and slots. Though I've figured out how to create custom slots, I've yet to figure out how do update the GUI from my C++ code. I realized that the entire UI, which I created in the designer, is only written in what appears to be XML based UI code. Do I have to handwrite my own Qt C++ UI in order to update the interface, or can I somehow use C++ to update the XML based UI? I'm just looking to add a widget to the main form on a button click. Any help is appreciated. Thanks!
To add a widget to a form you can simply do
ui->layout()->addWidget(new Widget);
XML is used by QtDesigner as a mean to create, update, and persist your GUI, enabling a visual approach to development, but in the end you can build your application entirely without it.
you dont havfe to update the xml of UI . you can inherit the ui into your own class using setupUi
http://crpppc19.epfl.ch/doc/qt4-doc-html/html/qwidget.html#setupUi
now in your C++ class you can update the widgets like changing label text, lineEdit text, setting up spinbox value using Signals & slot.
That xml is used by Qt designer and outside of designer it's only used by uic as a source to generate C++ code, so everything that you do in the designer end-up as C++ code, so it can be updated (or done completely) in C++ code (you can look into the code and see that you most likely have a member called ui that is most likely a pointer, but it can also be an instance of a C++ class that is generated for you by uic, and trough that ui member you can access the widgets and layouts that you created in the designer).
A generic resource that i recommend you to read can be found here and then (if you still can't figure it out) ask a specific question about what exactly are you trying to achieve.
LE: that link contains 3 methods to use the generated code into C++ code, don't try all of them into your working project, you may choose one method or use the default one (ui member pointer)

Singleton or Signal and Slots?

I am trying to reimplement or modify a tab code in a gui application. They are currently using Qt signal and slots system to handle addition and removal of tabs from the tab bar (For example if a tab was being drag from one tab widget to another, the old tab widget will signal the new tab widget that a new tab is coming). I was thinking rather than using that, I could simplify things using a thread safe singleton class. Then when ever a tab is moved, the widget just call on the singleton rather than emitting a signal.
Thanks
Signals and Slots.
Without even starting why the singleton would be bad, the way the data is updated inside Qt would be messed up by the singleton approach.
Don't do that. You are working within an environment and should use the mechanism the framework provides. What about if the UI in the future will have multiple windows and maybe multiple instances?
If possible you should always try to use the way from the framework you are using. This will also help in the future for the maintenance (upgrades, new hires, etc.)
You want to use a singleton, which will accept messages and dispatch them back ? (note: if you use a garden variety object instead of a singleton, you're essentially implementing an Observer pattern).
Then you are reinventing signals and slots, which use a global state internally. Instead of putting work in reinventing some difficult piece of code, why don't you use the already existing signals and slots ?