Command pattern for undo/redo: when to NOT merge undo commands? - c++

I'm implementing an undo/redo feature in our graphical Qt5-based app, using QUndoCommands which have a nice mergeWith() feature: for example, if the user repeatedly clicks the font size increase button on my app, rather than creating a ton of commands in the undo list, it just updates one command on the QUndoStack. So a single undo will go back to the original font size.
That's great, but there are times I don't want to automatically merge commands. For example, if I drag an item to a new location and drop it there, then drag the same item to another location: my app should create 2 move commands, not merge them both into one command.
So, here's a list of events that I think create a logical break, where the user will expect a command NOT to be merged with the next command, even if the next command changes the same property of the same object:
mouse release
widget lose focus
timer (after ??? seconds)
text typing, after ??? characters (or this can be handled with the timer?)
text typing, after certain keys are pressed, such as backspace?
As indicated by the question marks in my list, I'm not really sure in what situations to suppress merging commands. So my question is, are there any best practices in this regard? Where can I find them?

FWIW, I did not find any best practices, but for my software I suppressed merges on focus change (which in my app also occurs on mouse release on the graphics part). Additionally, for typing, I suppress merges if the input position changes in a way other that as expected for deleting or typing 1 character, and if the user switches between deleting characters and typing characters.
I did not bother with the timer, or with maximum characters when typing.

Related

How do you display rapidly updating data to the user in a win32 GUI app?

So im building a basic win32 GUI app and I have a vector of data that gets constantly updated through an external source via a port. Im interested in displaying that list of data to the user but im not sure the best approach to go about it without causing update flickering.
I originally had an edit box in which I build a string with the information and update the window. But it has proved troublesome as the amount of data grows since I cant scroll down to look at additional data. Any ideas?
My idea is no point of updating the visual control as the same speed you receive the data. Because even-though you update at the same speed the users cannot see that change at the speed of data receiving. Human eye does not see a change happening in speed as 1/8th of a second. So better to update the visual control in a controlled manner. Maybe using a timer.
Appending to the text of an edit control for each subsequent data point will lead to flickering as the whole control re-renders as the text has changed.
I'd advise one of the following options:
1) use a ListBox or ListView control; when you add another row item, it only re-draws the new/changed/scrolled item. https://learn.microsoft.com/en-us/windows/desktop/controls/create-a-simple-list-box and https://learn.microsoft.com/en-us/windows/desktop/controls/list-view-controls-overview
2) If you only want an always-scrolling list of data, consider just having a command-line application that writes to the standard output and saves you a lot of trouble - cout or printf your data.
You can also use EM_SETSEL and EM_SCROLLCARET to automatically scroll, but also check the position of the scroll bar before doing that. If not at the bottom, it means that the user wanted to pause, so you can scroll.
Also, you can have the scroll lock key checked in order whether to scroll or not, after all that is what it's name is supposed to do.

WXWidgets TextCtrl or RichTextCtrl

I'm using wxWidgets for a log window of a piece of software which runs for many hours. The log can accumulate 10,000's of entries. Does the community have a suggestion for how not to have the GUI thread choke for many seconds when updating a textctrl or richtextctrl with this many lines? I'm open to using either control type but richtext is preferable to I can highlight warnings or errors.
It's currently set to readonly, so undo, redo, paste, etc are not active. I'm currently freezing and thawing it before and after adding content.
In a test case, I add 10000 lines to the text control with a freeze and thaw before and after. This operation still takes over a minute. Are these text controls simply incapable of handling long content?
Assuming your display is like a log, where each "line" is it's own entry, try using the wxListCtrl in "virtual mode". Basically, you maintain the data in your own control (a vector, array, whatever works) and the control asks you for only the data that is currently visible.
Inherit wxListCtrl with your own class and implement OnGetItem. When a row is visible, your derived control will have this method called for each row (and each column if you implement multiple columns) and you provide it with the data for that row, accessed directly from your array (list, vector, whatever).
More information is available in the wxWidgets docs here: http://docs.wxwidgets.org/3.0/classwx_list_ctrl.html#a92370967f97215e6068326645ee76624
The suggestion to use wxListCtrl in #avariant answer is a good one, however a wxTextCtrl with wxTE_RICH style should still be capable of appending 10000 lines in well less than a minute if you freeze/thaw it before/after. I'd be curious to know if you can reproduce the problem in the text sample included with wxWidgets (which already has a menu item doing something like this) and, if so, which wxWidgets port do you use.

Two column TPopupMenu to list shortcuts right aligned

Using Borland/CodeGear/Ebarcadero C++ Builder 2009. Is it possible to show shortcuts (or other text), right aligned in a second column in a TPopupMenu ?
For instance:
[image] Open File ctrl-O
[image] Close File ctrl-W
[image] BlahBlah ctrl-B
etc.
If so, how ?
I checked the break property on an item, but the results is not exactly what I want, since items are selectable on their own, instead of the complete line. Also it's not drawn that nicely.
Your feedback appreciated.
A menu item can have an image (see the TMenuItem.ImageIndex property), and can have a shortcut assigned (see the TMenuItem.ShortCut property). The VCL will automatically draw those elements for you, exactly as you have shown.
By default, they are a little squished together. You can use the TMenuItem.OnMeasureItem event to extend the Width:
If you still do not like the way the default drawing looks, or you want different text than the ShortCut to appear on the right side, you will have to owner-draw the menu items yourself (see the TMenuItem.OnDrawItem and TMenuItem.OnAdvancedDrawItem events), then you can make the menu items appear however you want.

Lookup Combo that supports remote data - load data only after user wants to

I'm building a VCL c++ builder application. I would like to see if anyone knows of a component that can load data in the lookup upon drop down only after a user has typed a few letters to limit the rows queried? Preferably after pressing Tab, or Enter.
What I would like best is to get a behaviour similar to what Linux command line has, but that might be wishful thinking. The way it would work is to drop down the combo list after user presses tab only if there is multiple options available, and to fill in additional text till the point where characters are not the same anymore, then if user presses tab again, drop down list.
The next best would be if the drop down would only allow drop down if user has typed a few letters, then pressing a specific button opens the dataset with the parameter of the typed text so far, then drops down the combo.
Does a component like this exist?
You can check out TMS Software. I'm not sure if it has something exactly for you, but their components are quite flexible. And you can send a feature request to them - to consider for next update. If you are lucky they might add it to next release.

Implementing Undo feature (like Ctrl+Z) in Qt/C++

I am using Qt 4.5 and C++ on Windows XP.
Basically I will be having an UI where the user will enter some data. He can go and modify the values available in the UI. The UI will have basic Qt UI elements like QLineEdit,QTableWidget etc.,
So now, if the user presses Undo button (or Ctrl+Z) the previous value should be retained in the corresponding UI element.
Say, if there is QLineEdit with the text 25. Now the user modifies to 30. Now by clicking Undo, the older value 25 should be retained.
Like the Undo feature that usually available in many applications. Is there any way to do it?
You could use Qt's undo framework.
The typical way of implementing Undo is to represent each action done by the user, and store them. You also want the ability to compute the inverse of a given action.
So, for an insert into a text buffer, the action would store the text inserted, and the location at which the insert happened. The inverse then becomes a delete, at the same location and with the size of the inserted text.
When the user asks the application to undo, simply look at the most recent stored action, and execute its inverse. If you now instead of deleting the "spent" action remember it, too, you can implement Redo by moving the other way in the history of actions.
Note that this is an abstract and generic explanation; as other answers point out, Qt has a framwork in place for implementing Undo already, so you should of course investigate that, first.
You could use the Command Pattern to realize undo/redo
QLineEdit has a built-in undo/redo support, exported as public slots, check : http://doc.trolltech.com/4.7/qlineedit.html#undo