Widget-removed-event available? - qt

I have a panel that makes use of a simple vertical layout. From time to time some of the widgets in this panel are removed. What I want to do in such a case:
remove one of the separators that is placed between every of these widgets
rearrange the layout to avoid large gaps where the widget and separator have been removed
The problem is, such a widget deletes itself automatically, the parent panel not necessarily knows about this operation. Therefore my question:
Is there some kind of "child-widget-removed"-event available which can be received by the parent and can be used to start the procedure of re-layouting the panels contents as described above?
Thanks!

Related

'Manual' multi-selection in QTableView and partially hidden grid

I know that topic about multi-select arise at least once, but honestly neither can't find it anymore, nor remember that it had and decent solution.
There are two questions I propose to discuss:
1) Creating a behaviour similar to MS Excel cell's selection. So user click one cell in QTableView and gets clicked cell highlighted and in additional several 'dependant' cells change appearance (get selected or just gets highlighted in any way). In Excel it's widely used to show cell formula dependencies.
I know there are several approaches to solve it. Most simple one is to modify view selection with dependant cell in any of appropriate signal handlers (for example QAbastractModelView clicked()). That way does the job but has ugly side effect, that due to fact that signals delivered after redraw of selected cell occurs so dependant selection is drawn after first cell which produce flickering.
Second approach is go Delegate way.. That's also have some issues because you get paintEvent only for selected cell, so there is not that much you can do about 'dependent' cells. Actually I was able to solve it through this way, by catching on-click, modifying selection and using completely custom delegate which draws everything as soon as complete selection is formed, so actually it skips first redraw, but again I wasn't completely satisfy with results although visually it looked completely right.. mostly because overall TableView response time decreased a lot. Reasons for that is Qt draws native selection right after mouse click received before sending any signals to user classes and in case of this approach paintEvent in delegate arrives after several main loops. So there is a noticeable delay in case of using 'draw selection in delegate' in compare to 'draw native selection'.
I am already starting to think that best option can be completely overwrite most of QTableView to add support for such selection schemas, but may be there are more straight approach?
2) Second question (I put them together because there are something common issues).
Let say you have a grid representing financial information by months and within a month there are several columns of information, so block of N columns repeated M times. Obvious way to make such grid more readable is to use different style for vertical lines in grid for first data column in each month. Let's say to make them 1-2 pixels wider.
As you cannot specify grid style per cell, what I did was to setGrid(false) and then draw my own grid lines as a cell content in delegate.
But then I faced a problems from point 1. Then you instruct Qt to use delegate on certain cell, before delegate will get a paintEvent Qt clears a background of the cell. And in case of hidden grid the background rect which Qt clears is one pixel bigger then required. Probably it can be consider to be a Qt bug because they dont respect grid visibility, but this results in removing grid lines in neighbour cell, so you have to draw in delegate not only cell own grid, but also recalculate proper cell rectangle, check if Qt made a mistake (by analysing QPainter rect), decide if whats being removed from neighbour cell needs restore and repaint it also. This leads to really complicated delegate logic and I cannot consider it to be a decent solution.
So question 2 can be rephrased as do we know a decent way to style a grid per cell in QTableView?
OMG,so many words,can you just pick the most important info?
I'd do something like that:
Create a delegate. Subclass QAbstractTableModel and reimplement data method. Your implementation should return cell text for Qt::DisplayRole, but also can return whatever you want if role is one of your user-defined roles (like font or color or whatever of cell's text. You can use any role number above Qt::UserRole). Your model should emit dataChanged signal to notify QTableView that the content is changed and should be redrawn.
Then in delegate you just request this data using your overloaded QAbstractTableModel::data and draw it the way you want.

Qt hide QLayout (switch between two layouts)

I didn't find solution for my problem with two QLayouts. I need app with QHBoxLayout with possible expandind when I will add new widgets, push buttons, ....
So what I have: One QDialog and two layouts. Now I know that I can't hide the layout.
So I tray just :
layout()->removeItem(firstlayout);
layout()->addLayout(secondLayout);
But when I did this, I saw all items in first layout on possition [0,0].
So next step I try:
for (all items in first layout) if (widget) widget->hide();
But this is working only with QWidget and I have many different items in layouts.
Simply way is use the widget, because there is possible to use hide/show, but I need auto expanding window when I add new items.
Just rebuild the layout, there is no need to keep the two layouts in existence at the same time. Probably clearest is to have two (or more) methods, which first delete current layout, then create new layout, add widgets to it, hide all widgets you want hidden, and set it as current layout. Note that you don't even need to keep a member variable for the layout, since QWidget has that anyway and provides you with setter and getter.
Or, if you have different widgets in different layouts, and actually want to be able "switch pages" so to say, simply use QStackedWidget. Or if you have a fixed part (buttons etc), and then part with "pages", then put the "pages" into QStackedWidget, and keep fixed part out of it.
'addLayout(secondLayout/firstLayout) ' will remove the other layout automatically, you do not have to remove it. If you keep a pointer to the layout(which has addWidget() before), you can simply use the layout and widgets in it later. :)

How can I create a draganddrop wrapper inside a table row, that can represent the whole row

When I use treetable in Vaadin, it is working fine drag and drop the whole row when click the left and right blank ereas. but that is not user friendly, I wanna create a draggable layout inside the row, let's say the 1st component of the each row, that when clicking it, the whole row is selected and can be draged and dropped to reorder.
The thing is I can create a vertical layout with wrapper doing that, but drag mode is only for its component or the wrapper itself, and when doing the drag action, it doesn't actually showing the whole row is moving, which may confuse the clients. What can I do to make it looking like I am dragging the whole row, similar with the one you drag the blank area of each row? Thanks.
I'm afraid there currently is no way for adding a wrapper that would extend the entire row instead of just one cell. To do this you'd need to extend the client-side implementation of Table (VScrollTable) and this is not something I would recommend as it is quite complex.
I do think that what you describe should be possible in core Vaadin (without using drag & drop wrappers), so could you please file a ticket at dev.vaadin.com? And please attach a small application showing the problem to make it easier for us to see the problem and fix it.
Anyways, in order for you to get it working today I'd suggest that you change your UI design a bit and for example borrow drag handles from iOS. By this I mean that you could add an icon that suggests "draggable" as a background-image in the first cell (or in the row header cell of each row) that encourages the user to grab the row there, where it is "empty" and dragging works. This way the user might not be too confused if dragging only works reliably in some parts of the rows.

How to show only 30 rows and hide the remaining rows of QTableWidget

I'm having a QTableWidget with 10,000 records. I need to show only 30 rows at a time and hide the remaining rows. While dragining/clicking vertical scrollbar it should show corresponding rows and hide the other rows.
ie, if one clicks on upper scroll button it should show one more upper item and hide one lower item and vice versa. It should happen while scrolling as well.
Can anyone help me in doing this?
I think you can trap the events of up/down buttons as Nicholas said, for the tracking of slider/scroll bar u need use 'setTracking(true)'followed by the handling of signal either 'valueChanged(int)' or 'sliderMoved(int)'.
Thanks,
Pradeep
Qt unfortunately won't make this easy for you, there is ways and means of doing it however. Depending on how you're populating your widget I'd recommend setting it up so you initially populate your 30 rows, you then need to trap the signals coming from the scroll buttons being clicked and tell the table widget to remove the upper/lower item and add the next one, there's trade off's to this method, but it'll make it easier than trying to maintain a large list of hidden rows.
I don't know if explicitly showing/hiding things is the way you want to go. Instead, take a look at Qt's model and view classes. If you are using a database, have a look at QSqlTableModel, which should handle these things for you. Otherwise, have a look at the Model-View programming document, their related examples, and especially the portion about optimizing for performance (although in a model, 10,000 records isn't really all that many for most uses).
There is a way to change table scrolling from pixels to items. In Designer Property Editor for the table, in the QAbstractItemView section, there is a VerticalScrollMode selection. This can either be ScrollPerPixel or what you probably want, ScrollPerItem.
That may change the behavior of the signal from pixels to items which would make your calculations easier.
I'm using 4.4.3.

how to divide QGridLayout into rows and columns at Design Time in QT?

how to divide QGridLayout into rows and columns at Design Time in QT ?
I want to design one form where i want to have 2 columns and 7 rows .
I am designing using QTCreator but i am not getting any option of giving rows/columns.
It shows only these properties
See Using Layouts in Qt Designer. For you the most important paragraph is this:
The simplest way to manage objects is
to apply a layout to a group of
existing objects. This is achieved by
selecting the objects that you need to
manage and applying one of the
standard layouts using the main
toolbar, the Form menu, or the form's
context menu.
place your widgets on the form
arrange them into 2 columns and 7 rows
select all of them
right click on the selected widgets
select Lay Out in a Grid on the context menu.
You can often drag a new UI element to a position between two existing columns to create a new column - the GUI indicates that it's ready to create a new column by showing a blue vertical line to the user (same thing for creation of a new row with a horizontal blue line).
If instead it is showing a red line or outline, that's indicating that it will fit the element currently being dragged into the existing row/column grid at the indicated position, without creating a new row or column.
It can sometimes be quite difficult to get the GUI to play nice - I've have a number of occasions where I can follow this process to create a new column - but not if I try to place the UI element on the row I actually want it on - so instead I end up dropping it on another row to create the column, dropping another of the same UI element where I actually want it, and deleting the first (superfluous) UI element.
Alternatively, it can quite often be easier to simply right click the element with the layout set, select "break layout" from the layout menu, move things about manually and then go back and select "layout in grid" (or whichever other option) from that layout menu - hoping that it will correctly guess where you want things to go in terms of rows and columns. It's usually pretty good at that.
But yes, it probably would be nice to be able to force create a new column/row in a grid layout (perhaps with some default UI element - a label, maybe - inserted as a placeholder to keep the new row/column open) at a predefined position within the grid for those times when the GUI just does not want to play nice.
QLayout structure is created dynamically as you add widgets to it, there's no way to predefine how many rows/cols a layout have.
Maybe you are using the wrong approach to achieve your goal.

Resources