MFC: what is the best way to generate and display large document? - mfc

I am still new to this area. My current project requires to generate and display large report (over a few hundred pages). The structure of document is quite simple but still contains row-column formatting with a few colors, fonts and lines. Also, it needs to be printable which is quite a headache. The approach I am taking is to use browser control plus HTML. One issue is that when the document gets big, UI is pretty lagging. Is there other way of doing that?

Related

How to fast append to QTextEdit

I have an application that has some sort of log viewer, that needs to be able to render formatted log records that are inserted to it in real time.
I am writing this in Qt and so far I was using QTextEdit for rendering of the text, which was beautified using some html tags and later inserted either with setHtml or insertHtml.
The problem is however, that these functions are insanely CPU intensive and run for ages, hanging whole application.
A similar question was asked here: QTextEdit.insertHtml() is very slow
Apart it has no really useful answer, other than stating it's really slow, it actually asks a different thing. I don't need to speed up setHtml or insertHtml. I am willing to use entirely different technique if possible.
Is there any mechanism within Qt that would allow for really fast insertions of text? Or maybe even completely different component than QTextEdit?
Is there any way to append new line to QTextEdit which contains rich text (generated in any way) that is really fast?
I also noticed QTextBrowser but it seems to be just an extension of TextEdit, could it be faster?
You should give QPlainTextEdit a try. It uses the same technology as QTextEdit but is a lot faster. It is optimized for plain text handling but do not let that fool you, it still has some basic support for formatting using HTML. You can append HTML formatted text with appendHtml().
In my application, I also need to display a large log of the task, approximately 3500 lines. Some lines of the log should be colored. For this, I used HTML formatting. QTextEdit.setHtml with this amount of text, freezed my GUI.
I replaced QTextEdit with QListWidget, in which QListWidgetItem is created for each line of the log.
It began to work much faster, without friezes.
And I saved colored text, just simple by using the QListWidgetItem.setForeground.
[This post][1]
[1]: Performantly appending (rich) text to QTextEdit or QTextBrowser in Qt contains an answer to this problem. The gist: instead of simply appending an HTML snippet, manipulate the underlying document directly.
However, I suggest that if your display really is a list of single lines, you create a QAbstractListModel QAbstractTableModel derived class instead and show it in an item view.

xslfo with FOP: Check if content overflows and call different template?

I have a question with XSLFO, generator is FOP. What I wanna do:
In the PDF I wanna generate an item list, each item is in a box with a specific width and height. In case the content does not fit this box, the content should be displayed in a bigger box (with also specific dimensions).
I do not see any way to reach that in XSLFO, especially with FOP.
Has someone an idea to solve that?
Thanks for every idea!!
There are two separate, independent processing steps involved here:
Generation of XSL-FO markup (using a stylesheet and an XSLT processor).
Rendering of XSL-FO markup as PDF (using a FO processor, such as FOP).
The second step cannot influence the first. It is not possible to test for overflow conditions during rendering and somehow decide what template to invoke. There is no feedback loop. What you are asking for is not possible.
It is possible to do crude text fitting by estimating the length of text strings in XSLT. That is the idea behind "Saxon Extension for Guessing Composed Text String Length".
I have not used this extension, and it may not even be available anymore (the announcement about it is from 2004). In any case, this is very far from an actual layout feedback mechanism.

help with type of window dialog resource needed

I am writing a windows program (no mfc) and need to output a status line to the operator every few seconds or so. I tried using rich text boxes but after so many hours it seems to hang up. Does anybody have an suggestions on what I can use instead?
People mentioned that my buffers might have been exhausted. I thought I had planned for that. After I had about 1000 lines displayed I would take the first 500 and remove them using the select and cut options in rich text boxes. I still ran into the same problem.
This question appears relevant, and this one too. But they don't give any concrete recommendations for an alternative to rich text boxes.
You might try the Scintilla control (scintilla.org) which does not appear to have any hard limitations on text size. It has a permissive license. It is used by many text editors such as Notepad++, Notepad2, Code::Blocks, FlashDevelop. I haven't tried it personally but there from the documentation it looks easy to use it in a Windows API application. Of course, it might be overkill for your purposes.
If you keep appending to the text in the control every few seconds for hours then you are probably running into some memory constraint on the control or the process. I think you would have this problem with any control you choose given update frequence and how long you're running the program.
Have you considered implementing a simple circular buffer for the content of the text box? Say only keep the last hour's messages. You could maintain a separate log file for history if the operator needed to go back in time for hours.
I ended up writing my own control to do this, essentially duplicating the Output window in Visual Studio. It was a success, but it ended up being much more code than I thought it would be when I started - I insisted on features such as auto-scrolling when the cursor was on the last line, select/copy, bold text, etc. It was backed by a std::deque so I could limit the number of lines stored for the window.
Unfortunately the code belongs to a former employer so I can't share it here.

Html renderer with limited resources (good memory management)

I'm creating a linux program in C++ for a portable device in order to render html files.
The problem is that the device is limited in RAM, thus making it impossible to open big files (with actual software).
One solution is to dynamically load/unload parts of the file, but I'm not sure how to implement that.
The ability of scrolling is a must, with a smooth experience if possible
I would like to hear from you what is the best approach for such situation ?
You can suggest an algorithm, an open-source project to take a look at, or a library that support what I'm trying to do (webkit?).
EDIT:
I'm writing an ebook reader, so I just need pure html rendering, no javascript, no CSS, ...
To be able to browse a tree document (like HTML) without fully loading, you'll have to make a few assumptions - like the document being an actual tree. So, don't bother checking close tags. Close tags are designed for human consumption anyway, computers would be happy with <> too.
The first step is to assume that the first part of your document is represented by the first part of your document. That sounds like a tautology, but with "modern" HTML and certainly JS this is technically no longer true. Still, if any line of HTML can affect any pixel, you simply cannot partially load a page.
So, if there's a simple relation between position the the HTML file and pages on screen, the next step is to define the parse state at the end of each page. This will then include a single file offset, probably (but not necessarily) at the end of a paragraph. Also part of this state is a stack of open tags.
To make paging easier, it's smart to keep this "page boundary" state for each page you've encountered so far. This makes paging back easy.
Now, when rendering a new page, the previous page boundary state will give you the initial rendering state. You simply read HTML and render it element by element until you overflow a single page. You then backtrack a bit and determine the new page boundary state.
Smooth scrolling is basically a matter of rendering two adjacent pages and showing x% of the first and 100-x% of the second. Once you've implemented this bit, it may become smart to finish a paragraph when rendering each page. This will give you slightly different page lengths, but you don't have to deal with broken paragraphs, and that in turn makes your page boundary state a bit smaller.
Dillo is the lightest weight Linux web browser that I'm aware of.
Edit: If it (or its rendering component) won't meet your needs, then you might find Wikipedia's list of and comparison of layout engines to be helpful.
Edit 2: I suspect that dynamically loading and unloading parts of an HTML file would be tricky; for example, how would you know that a randomly chosen chunk of the file isn't in the middle of a tag? You'd probably have to use something like SAX to parse the file into an intermediate representation, saving discrete chunks of the intermediate representation to persistent storage so that they won't take up too much RAM. Or you could parse the file with SAX to show whatever fits in RAM at once then re-parse it whenever the user scrolls too far. (Stylesheets and Javascript would ruin this approach; some plain HTML might too.) If it were me, I'd try to find a simple markup language or some kind of rich text viewer rather than going to all of that difficulty.

How do I append a large amount of rich content (images, formatting) quickly to a control without using tons of CPU?

I am using wxWidgets and Visual C++ to create functionality similar to using Unix "tail -f" with rich formatting (colors, fonts, images) in a GUI. I am targeting both wxMSW and wxMAC.
The obvious answer is to use wxTextCtrl with wxTE_RICH, using calls to wxTextCtrl::SetDefaultStyle() and wxTextCtrl::WriteText().
However, on my 3ghz workstation, compiled in release mode, I am unable to keep tailing a log that grows on average of 1 ms per line, eventually falling behind. For each line, I am incurring:
Two calls to SetDefaultStyle()
Two calls two WriteText()
A call to Freeze() and Thaw() the widget
When running this, my CPU goes to 100% on one core using wxMSW after filling up roughly 20,000 lines. The program is visibly slower once it reaches a certain threshold, falling further behind.
I am open to using other controls (wxListCtrl, wxRichTextCtrl, etc).
Have you considered limiting the amount of lines in the view? When we had a similar issue, we just made sure never more than 10,000 lines are in the view. If more lines come in at the bottom we remove lines at the top. This was not using WxWidgets, it was using a native Cocoa UI on Mac, but the issue is the same. If a styled text view (with colors, formatting and pretty printing) grows to large, appending more data at the bottom becomes pretty slow.
Sounds like the control you are using is simply not built for the amount of data you are throwing at it. I would consider building a custom control. Here's some things you could take into account:
When a new line comes in, you don't need to re-render the previous lines... they don't change and the layout won't change due to the new data.
Try to only keep the visible portion plus a few screens of look-back in memory at a time. This would make it a little lighter... but you will have to do your own scroll management if you want the user to be able to scroll back further than your look-back and make it all appear to be seamless.
Don't necessarily update one line at a time. When there is new data, grab it all and update. If you get 10 lines really quickly, and you update the screen all at once, you might save on some of the overhead of doing it line by line.
Hope this helps.
Derive from wxVListBox. From the docs:
wxVListBox is a listbox-like control with the following two main differences from a regular listbox: it can have an arbitrarily huge number of items because it doesn't store them itself but uses OnDrawItem() callback to draw them (so it is a Virtual listbox) and its items can have variable height as determined by OnMeasureItem() (so it is also a listbox with the lines of Variable height).