WXWidgets TextCtrl or RichTextCtrl - c++

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.

Related

QTreeView scroll to current row after sort

I'm adapting QT Creator Basic Sort/Filter Model Example to work with my own source data (my movie library). That link shows what the example display looks like, and here's a link to the relatively small amount of source code. I don't really understand everything I'm doing, but mostly things have gone well until I hit this current problem...
How can I update the view so currently-selected row ALWAYS stays visible after changing sort order?
I hope someone will tell me exactly what C++ code needs to added / modified in the actual example program. There's probably no point in posting links to QT documentation, or "similar" code doing much the same thing in other contexts, because I don't think I'll be able to understand how to adapt such information to my own needs.
I'm using latest QT Creator 6.0.2 running under latest Linux Mint 20.3 Cinnamon, but I'm not sure that makes any difference, and I don't know what if any other information might be relevant.
EDIT:
I assume the extra code to force "scroll to current selection after sort" logically fits in QT Creator source code file examples/ widgets/ itemviews/ basicsortfiltermodel/ window.cpp
I commented out line 122 in that file (suppress display of the "source" table, because I only want the "proxy" view). Other than that, the source file in my derived project is identical to the original as held here on GitHub (along with the header & main source for the example project, per my second link above).
Effectively, I'm asking for the smallest possible change to the actual example project code to ensure the currently selected line never disappears from view after sorting.
The exact example from QT documentation has less than a dozen rows of data, so exact control of display positioning doesn't matter much. But I'll normally have a lot of rows visible, and the currently selected row could appear at any position within the visible window. Sometimes, "current row" might not actually be visible before a sort, but I'd like it to always be visible after.
It might be asking a lot, but I'd be seriously impressed if anyone comes up with succinct code to ensure that wherever possible, the currently highlighted row stays in position (doesn't jump up or down) while the rows above and/or below change as a result of sorting.
If you want to scroll to current row after sorting, then I would suggest doing the following four changes to your code.
You should implemented your own model by inheriting from QStandardItemModel and in this derived model class:
add a signal sorted() to your model class
override virtual method sort() (https://doc.qt.io/qt-5/qabstractitemmodel.html#sort)
void YourModel::sort(int column, Qt::SortOrder order = Qt::AscendingOrder) override
{
QStadardItemModel::sort(column, order);
emit sorted(); // this is the signal you added
}
Then create a method which will access the tree view and would do this:
void scrollAfterSort()
{
treeView->scrollTo(treeView->currentIndex());
}
Connect YourModel::sorted() signal to this scrollAfterSort() method.

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.

Is it possible to create multi column combobox by subclassing only its listbox?

In MFC, is it possible to create multi column combobox by subclassing only its listbox.
In Codeproject and Codeguru websites I got samples only with derived CComboBox with ownerdraw style.
The "list" part of a combo-box control is NOT a list-box control. Apart from this, combo-box controls do not really have "columns", and this means that you cannot store column-level data (there is just one string or "item" per row), and subsequently any solution visually imitating "columns" can only be owner-drawn-based. So, if your app's specs have changed (now requiring column formatting) you should rather consider using another control type. Still, an owner-draw implementation isn't really that hard, esp if you have fixed height items; it shouldn't really require extensive changes to your app, as it concerns this specific control only.

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

Refresh text shown in a GTK+ widget?

Being resonably new to using GTK+, im not fully aware of all its functionality.
Basically, I have a GtkTreeView widget that has 4 Columns. I need to update the text displayed in the 4 columns every couple of seconds, but im not aware how to do this in GTK+.
I'm aware that I could flush the data using gtk_tree_store_clear, but I'm not sure how to repopulate the columns and have the top level window refresh to show this new data?
You need to get a GtkTreeIter to the proper row, then use the appropriate (model-specific) setter to change the data.
For instance gtk_list_store_set() for the GtkListStore model.
There is no need to clear the entire model if you just want to change some of the data, that is very wasteful and slow.
If you really need to change all the data, then sure, clear it.
You don't have to worry about getting the display to refresh; the view listens to events from the model, and automatically knows to refresh when the model changes.
UPDATE:
When changing the data (as described in commment), you don't need to "flush" the old data. The model owns the data, and knows how to keep track of the memory used. You just use the above-mentioned gtk_list_store_set() call as necessary to put the new desired data in the model. You can do this as often as necessary, and an update frequency of once every few seconds should be no problem at all.
Of course, in such a case, to keep your application (which I assume is single-threaded, for simplicity) responsive, you must have a way to asynchronously trigger an update, perhaps using a timer. Have a look at glib's g_timeout_add() function to learn how to add a simple global timer.