QPainter colored text (syntax coloring) - c++

I have a custom Qt widget which I used to display disassembly and I am looking to add syntax coloring to it.
Currently, I simply set the QPen to a solid color, construct the text I want to display, and render it to the QPainter at the appropriate coordinates.
The question is, what is the best approach to adding syntax coloring? I've thought of a few:
I could simply divide the coloring into logical blocks, each preceded by setting the QPen to the desired color.
I could have special escape characters which represent a change in the color palette, and render 1 character at a time.
I could do a modification of #1 and create a list of std::pair<QColor, QString>, then I could simply iterate the list setting the color and drawing the text as I pop items off the front of the list.
Something entirely different?
I know that each of the 3 approaches I've listed will technically work, but I'm looking for a very efficient solution. This code will be called a lot. And since this is an interactive debugger, if this code is slow, someone rapidly stepping or tracing will see a visible slowdown.
EDIT: I'm aware of QSyntaxHighlighter and QTextDocument. The main issue is that these don't generally suite my purposes very well. I have several columns which all have dividers and can be slid back and forth. To give you an idea, Here's a link to a screenshot of my debugger. As you can see it isn't really like a text document at all. In fact it is closer to a list or table. But there is already a bunch of custom drawing going on making a normal QTextDocument somewhat impractical.
EDIT: I was incorrect, It seems that QTextDocument can render directly to a QPainter. Looks like what I need!
EDIT: It is unclear how to control where and how QTextDocument or QTextLayout will draw on a QPainter. I've attempted to use them to no avail. So if someone could provide a rudimentary example, that would be very helpful.
EDIT: I was eventually able to get what I wanted using something like this:
painter.setPen(default_color);
QTextDocument doc;
doc.setDefaultFont(font());
doc.setDocumentMargin(0);
doc.setPlainText(text);
highlighter_->setDocument(&doc);
painter.save();
painter.translate(x, y);
QAbstractTextDocumentLayout::PaintContext context;
context.palette.setColor(QPalette::Text, painter.pen().color());
doc.draw(&painter, context);
painter.restore();

Qt provides a QSyntaxHighlighter that is probably exactly what you want. QSyntaxHighlighter uses a QTextDocument to mark each block of code with a specific state which can be associated with a specific presentation format.
The documentation on QSyntaxHighlighter provides a sample demonstrating how this may be accomplished and does some nice things:
Separates the model from presentation
Separates the formatting into different reusable classes (if implemented as such)
Supports the State design pattern if useful to your language

I'd use either QTextEdit or directlay its underlining engine QTextDocument.

Related

How to draw a line (or arrow) from one object to another in run time using Qt

I have to design a GUI using Qt. I would like to draw multiple lines depicting relationships between two objects. It's the same idea as matching a word with a definition by drawing a straight line (which might be a diagonal) between the two.
In my case it is an a label (with image inside of it) that needs to be matched with another label.
So we have something like this - http://dl.dropbox.com/u/46437808/DrawLines.png
And I want to add lines to make it look something like this http://dl.dropbox.com/u/46437808/DrawLines2.png
I need to do this in run time because the relationship will be changing based on different factors.
Thanks!
Do you need interaction or is this just an image that the user needs to see based on other information? If it's just a static image, I would simply draw it onto a QImage and show it. That way you have complete control over how things are drawn. So you can either cache the relationship diagrams you need ahead of time, or just draw them on the fly onto the QImage based on the relationship that needs to be displayed at the time. You can look at Qt's painting example for some ideas on how to accomplish what you need.
If you need interactivity, I would probably go with the Graphics View Framework. This way if you need push buttons, check boxes, etc. for any reason you can use the QGraphicsProxyWidget to get them, or you can just make your own from QGraphicsItem subclasses.

How to make a raster in the background of a panel/tabPane/s.e

I try to create something, where you can drop different things on it, like the Qt Creator (no, i don't want to create a new one, but i need the function of that).
You drag some elements and drop them anywhere in a tabPane.
My problem now is how to make a grid/raster in the background.
It should look similar to this:
I mean those dots in the background.
If I make them with two for loops, it will take hours and it's not efficient or anything else.
There has to be a more efficient solution and a lot easier one.
I'm programming in c++ with Qt as a Framework. Please give me some links or anything else I can use.
You can:
limit the repainting to region that really needs to be updated as explained in QWidget::paintEvent documentation,
fill a container of QPoint in your loops instead of drawing the points, and draw them all with QPainter::drawPoints after the loop,
cache the result in a QPixmap with transparency and reuse it if the window size didn't change (example from Qt Quaterly).
Of course, you should do some testing to see if you gain anything at all by doing any of these optimizations.

How can we create custom slider?

I want to create a slider which contain a different slider handle and i want to paint it according to slider handle position in the slider.
You could use QProxyStyle to ovrride drawComplexControl method - you will have to draw entire control on your own, as there is no separate flags in QStyle::ControlElement for parts of QSlider.
maybe you should look at this: http://doc.qt.io/qt-4.8/stylesheet-examples.html#customizing-qslider
If I understand you correctly, you want a slider that changes not only its position but also its appearance as you slide, right? For example, a mix of QDial and QSlider, ie. a slider with a turning knob.
If so, you will need to subclass either QSlider or QAbstractSlider (or QDial) and do the painting in your own paintEvent(). Note, however, that you will loose all style-awareness unless you care about that yourself (and that is an interesting topic in itself, see http://doc.qt.io/qt-4.8/style-reference.html for more info).
The Qt demos and examples, or the QSlider/QDial source code itself may serve as examples on how to overload a paintEvent().

What makes a Qt widget and its layout behave properly (in regard to its size)?

I'm having all sorts of size problems with Qt. I am creating my own widgets and using different layouts (generally, I need my own to make them work properly without spending hours on the "powerful" default layouts... which don't lay things out as intended.)
Once I'm done with a widget and its layout though, it doesn't work right. The size is never getting set properly unless I call widget->resize(1, 1); which finally forces a "resize" and makes the widget look correct (i.e. recompute the geometry.) Even the updateGeometry() call has no effect.
This is a dreadful problem when the resize() needs to be called on the parent widget (yuck!) and from what I'm reading should not be necessary were the layouts properly programmed.
Is there a sample that works and is not several thousand of lines long, or does Qt require several thousand lines to make anything work perfectly, even the simplest widget?
What are the minimal functions to be called to make a widget & its layout work at once?
Thank you.
Alexis
P.S. I tried to implement the sizeHint(), minimumSize(), maximumSize(), others that I'm missing? I was hoping that would be enough. Obviously, I also implement the setGeometry() on the layout to resize the children appropriately.
--- addition 1
There is a sample image with a layout that clearly isn't available as is in Qt. The positioning, functions, and colors of the different keys is XML driven and works for any keyboard in the world.
(note, this sample doesn't show the Enter key displayed on two rows and wider below than at the top; more or less, not doable at all with the regular layouts; of course, it works with my version.)
--- clarification
I'm not too sure how to describe the problem better. I was thinking to write a test widget next to see how I can reproduce the problem and then post that and eventually fix it. 8-)
The default layout function that the internal Qt layouts make use of require a lot of coding. I would like to avoid having to copy/paste all of that because for maintenance, it makes it close to impossible.
--- today's findings
As I needed to tweak one of the widgets, I decided to add a VBoxLayout and make it work.
I actually found the problem... One of the widgets in my tree is a QScrollArea and that sizeHint() returns (-1, -1). Not exactly what I'd expect but... whatever you put inside that widget has better know how to compute its width and height or else... it fails.
Looking at the code closely, I could actually compute the width by using the widest width found. Once I used that, the widget would appear (and it actually resizes itself as things change in the list, kinda cool.)
This being said, my earlier comment about having a tree of widgets that auto-resize themselves stands. From the root up to the parents of the leaves in your tree, all of those widgets will need a valid layout. Once I added one in the top widget it resized itself and its children properly (well... in my case up to the QScrollArea, the rest required a bottom to top resizing. Funny how that works!)
--- ah! ha! moment (or: what you find reading the implementation code!)
Today I bumped in another problem which just needed the correct call... I just couldn't find anything worth it in the documentation.
All the objects have a layout now, but a certain parent would not resize properly. Plain simple.
I had a call to the parent as following:
// changes to the children are changing the geometry
parentWidget()->updateGeometry();
Yeah. The docs says that's what you have to do. Nothing happens at all with that call. No idea what it's supposed to do, I did not look at that function. It never did anything for me anyway.
So... I looked at the layout to try to understand how it would send the info up/down. I did not see much except for one interesting comment:
// will trigger resize
This is said of the SetFixedSize mode. To reach that function you need to make the layout for update. Ah! Yes... the layout, not the parent widget... let's try that instead:
parentWidget()->layout()->update();
And voila! It resizes correctly in all cases I have. Quite incredible that the widget updateGeometry() doesn't trigger the same effect...
Although it's possible to do what you want it sounds like the problems you are having are because you're using Qt in a way that it's not meant to be used. Why do you need separate widgets for each key represented on the keyboard?
I see two options, both of which are better in some way:
Use QGraphicsScene and QGraphicsView.
A single custom widget that uses custom drawing to display the keyboard (and likely uses hover for hints).
The first option is probably better. Your keys could then be represented by QGraphicsSimpleTextItem's or even a QGraphicsSvgItem. It also provides a number of standard layouts or you could choose to write your own layout. By default you can use the keyPressEvent or mouseReleaseEvent to respond to user interactions.
I'd highly recommend you take a look at the QGraphicsView examples to get an idea what you can do.
If you go the second route you'll need to record the different key locations so you can respond accordingly as the user moves the mouse around, clicks, etc.
This won't help you with your immediate issue but I wanted to show you a keyboard I made using standard layouts and buttons. It's not perfect and it still won't help you with an enter key that spans two rows but it's not bad. It's resizable too by resizing the window, although I'm not sure if that will be apparent from the images below as SO may be scaling them. (you can view the actual images by opening them in their own tab)
Anyway, this was done using only Qt Designer with no manual coding. It consists of a top level vertical layout with 5 horizontal layouts in it. The buttons are then inserted into one of the 5 horizontal layouts. The size of the keys can be controlled by setting the horizontal and vertical size policies to "ignored" for most of the buttons and then horizontal "minimum" for buttons that you want to be wider. Things can be tweaked by setting min and max size restrictions to buttons. When resized, the buttons will not maintain their relative proportions though, that would probably take some custom programming.
The styling in your example could be approximated pretty well using css style sheets and background images. Still not a minor effort but you should be able to get most of the way there without custom layouts and buttons.

QT Creator c++ writing Kakuro puzzle and unsure of what widget to use

I'm using QT creator and have all my methods etc designed and trying to design a UI and I'm not sure what widget I should be using to reference my puzzle layout.
I've been reading over the documentation for a while and I still am nowhere closer to finding a solution to what I should be using to display my values. I know what I should like but all I seem to find information on is various layouts of entry boxes that are in no way linked. I have no problem with coding it myself to communicate with my classes if I just knew what to use to start off with.
I need something that can help me create a layout that has up to two numbers with positions specific to the type of hint it is with a slash between the hints, black blocks that are neither hints nor stored values and squares that have values that can take up the whole square.
Layout is something similar to http://www.nikoli.co.jp/en/puzzles/kakuro/
I wish I knew what to pick >.<
Personally I'd use QGraphicsView and handle the drawing myself.
It can draw rectangles, triangles, circles and text without much effort, and that's pretty much everything you need as far as I can see. You just need to add the objects to a QGraphicsScene and you get them on the screen. You can also interact with the objects (you can find which object you're pointing at etc.)