C++ Qt QTableWidget item moves when resizing column - c++

I am writing a C++ plugin for an existing application where I need to display a window which contains a QTableWidget using Qt.
Here is an excerpt of my working code where I am building the QTableWidget and filling the cells.
tableWidget->setRowCount(0); // clear tablewidget
tableWidget->clearContents();
tableWidget->setColumnCount(5);
tableWidget->setRowCount(2);
QStringList header;
header << "Date" << "Owner" << "Type" << "Folder" << "Path";
tableWidget->verticalHeader()->setDefaultSectionSize(20);
tableWidget->setHorizontalHeaderLabels(header);
tableWidget->setItem(0,0,new QTableWidgetItem(QString("dog")));
tableWidget->setItem(0,1,new QTableWidgetItem(QString("cat")));
tableWidget->setItem(0,2,new QTableWidgetItem(QString("frog")));
tableWidget->setItem(1,0,new QTableWidgetItem(QString("shark")));
tableWidget->item(0,0)->setTextAlignment(Qt::AlignLeft);
tableWidget->item(0,1)->setTextAlignment(Qt::AlignLeft);
tableWidget->item(0,2)->setTextAlignment(Qt::AlignLeft);
tableWidget->resizeColumnsToContents();
It works as expected, except the data inside each successive column is moved further right than the previous column. This can be exaggerated when you resize a column and see the data in columns to the right "slide" even further right.
Here are 2 screenshots of the effect (before and after column resize). You can see how the words "cat" and "frog" have moved more to the right than normal.
What am I doing wrong? I want each cells text to be aligned to the left of each column.

The root of the problem appears to be related to Windows Display settings.
My laptop text display setting was set to "Medium - 125%".
When I set it back to "Smaller - 100%" then the problem went away.
I would still like my program to work properly if the user should use 125% text, but at least now I know the cause.
Does anyone know how I to prevent the above problem when using 125% text?

Related

QTableWidgetItem displays three dots instead of full text

I'm using a QTableWidget with four column witch i programaticaly fill with QTableWidgetItem in a loop. it's working but the full text is not displaying, it show three dots instead like there isn't enough space:
if i double click on a row it will display the whole text:
How to set QTableWidgetItem programatically to fill all available space, or disable the 3 dots system and just display the whole text event if it will overflow ?
Here my simplified code that just fill the second problematic column:
vector<OperationLine> lines = db->getOperationLines(ui->dateEditFrom->date(),ui->dateEditTo->date());
ui->operationTableWidget->setRowCount(lines.size());
ui->operationTableWidget->setTextElideMode(Qt::ElideNone);
for(int i=0;i<lines.size();i++){
QTableWidgetItem* libelle_item = new QTableWidgetItem(lines.at(i).libelle);
libelle_item->setToolTip(lines.at(i).libelle);
setDocumentMode(libelle_item);
libelle_item->setSizeHint(QSize(500,50));// <-does not seem to work
ui->operationTableWidget->setItem(i,1,libelle_item);
}
ui->operationTableWidget->resizeColumnsToContents();
ps: OperationLine is a simple class and .libelle is just a QString. Manualy resizing the column does not help. I also tried to disable editing and it does not help either. However if i comment my loop and manualy add item with QtCreator it seem to work as expected.
My original string contain return lines, removing them like:
QString s = lines.at(i).libelle;
s.replace('\n',' ');
ui->operationTableWidget->setItem(i,1,s);
is working.
As #Scheff'sCat pointed out in the comment of my original post, using the accepted solution at How to prevent too aggressive text elide in QTableview? work too and will display multiple lines withouts the dots in the wrong place.

How to hide the first column of a wxListCtrl in wxWidgets?

The context
In a wxWidgets (version 3.0.2) C++ application, I am trying to hide the first column of a wxListCtrl.
I did not find a member function to do this so I tried to set the width of the column to 0:
myListCtrl->SetColumnWidth(0, 0);
first argument being the column ID and second one the width in pixels (wxListCtrl documentation).
After running the program, the header of the first column is hidden as I wanted but the data of each row of the first column overlaps the data of each row of the second column (which is not hidden). It is obviously not what I want. The header and the data of the first column should be hidden.
The question
In wxWidgets 3.0.2, is there a way to hide the first column (header and data of each rows) of a wxListCtrl?
I don't believe you can. You have a few options.
Delete the column using DeleteColumn(int columnIndex). You aren't losing any data, just the display of it, so you can always re-insert the column and repopulate it if you need to re-add it. Obviously this could be time consuming if your data is excessively large.
Depending on your application, just don't create the column in the first place. You don't say why you want to hide it, so if you just don't want it, don't add it.
Implement your control as a virtual control which gives your application control over what to display where. The burden of data display management falls to you to do manually but you have a great deal more flexibility. Inherit the class with wxLC_VIRTUAL style and implement OnGetItemText http://docs.wxwidgets.org/3.0/classwx_list_ctrl.html#a92370967f97215e6068326645ee76624
Edit:
To expand on the comment question, how to get the selected item index:
The wxListCtrl is a little weird when it comes to selected items. I'm sure it has to do with needing to support report, icon, etc. different views. When dealing with a multi-column report mode, you might find that you can only select items in the first column. If you are on Windows, it should automatically be set to "Full Row Select" but I don't know about other OSs.
Anyway, here is a utility method that returns the first selected item (note that you can support multi-selection if you want to).
//Get the item currently selected
int ListView::GetItemSelected() const
{
for(int i=0; i<GetItemCount(); ++i)
if (GetItemState(i, wxLIST_STATE_SELECTED) == wxLIST_STATE_SELECTED)
return i;
return -1;
}
If you want (and it makes sense), you can connect the list item selected event.
this->Connect(wxEVT_COMMAND_LIST_ITEM_SELECTED, wxCommandEventHandler(ListView::selected_Changed), NULL, this);
and within that event handler, get the selected item and do what needs doing (depending entirely on your application).
You will note that I'm using a derived class here which just makes things a lot easier but you don't have to. You can connect to something like MyMainForm::sqlResults_selectedChanged or whatever.
There is more than one way to accomplish all this and you can also find some good suggestions and help here: https://wiki.wxwidgets.org/WxListCtrl

Qt C++ - How to get the current Row and Column of a QPlainTextEdit

Hello World, I am working on a text editor in Qt c++ and I would like to know how to get the current row and column of a QPlainTextEdit. The reason I need it is to put it on the status bar of my app and I have no IDEA on how to do it. Please help me.
Call the QPlainTextEdit's textCursor() method to get a QTextCursor object representing the current position of the text-editing caret. You can then call blockNumber() to get the current row, and positionInBlock() to get the position within the row (i.e. the column).
You'll probably also want to connect the QPlainTextEdit's cursorPositionChanged() signal to a slot in your program, so that you can update your display as the text-cursor moves around.

QTableView re-focus the view to specific column

I have a QTableView with 80+ columns displayed in it. The subclass i have created for QTableView allows has functionality for the standard table stuff i wanted e.g order by columns move columns and rows hide column and rows etc.
However the problem i have is the view's focus. lets say you have all the data in the table, you scroll all the way to the right so you are looking at columns 70-80 (assuming 10 columns fit on the screen at once) if i click the header of row 80 (to order by column 80) the table reorders (as expected) however it also jumps the view to the last focused cell (which as far as i can tell is the cell that was last clicked)
What i want to do is not necessarily refocus on the column that was clicked because this might still change the view what im looking for is to just keep the view's focus exactly as it is instead of having it jump back to where the last clicked cell was?
Is there some flag im missing for focus policy or will i need to get the current view and set the view back to that view after mouse clicks that reorder the table and if so how could this be done.
Im aware i have provided no code for this question but it doesnt seem there is any needed since its not a bug im looking to fix more of a feature im unaware of, if you want to see any just comment
EDIT:
Im using a QSortFilterPorxyModel, this seems to get set once (when i call this->setSortingEnabled(true); after the initial call to this on contruction my table model never calls sort again. I have a slot linked to the header clicked signal, and i set the scroll bars to scrollTo() to the index clicked, but i think the sort is happening after this so it does nothing, any idea of what signal are emitted after sorting so i can catch them and then set the view back maybe?
thanks
Before you do your sort, store the current values for where the scroll bars are with
int vPos = yourQTableView->verticalScrollBar()->sliderPosition();
int hPos = yourQTableView->horizontalScrollBar()->sliderPosition();
then after the sort, set it back
yourQTableView->verticalScrollBar()->setSliderPosition(vPos);
yourQTableView->horizontalScrollBar()->setSliderPosition(hPos);
The signals you are looking for are signals of QSortFilterProxyModel inherited from QAbstractItemModel:
layoutAboutToBeChanged()
layoutChanged()
I couldn't reproduce your symptoms by creating a QTableWidget, filling it up with random stuff, and then sorting a particular column. The selected cell stays selected, but does not become visible if it has scrolled off screen.
So the question is, what is causing the behavior you're seeing. It sounds as though scrollTo() is being called by some other function. Since that's a virtual function, I would override it with a pass-through function and see when it's getting called.

Infragistics WebDataGrid column layout not maintained on Insert and Delete

I've come across this weird issue with the Infragistics WebDataGrid control.
When the grid starts, it appears ok, headers on the header row. There are no entries, so the only row displayed below is the "add" row.
I then load data into the grid from my AJAX code-behind. It appears ok. The 3 new rows appear, the "add" row sits below. Everything clean.
I then click the delete "x" in the 2nd row (sidenote: this is a template column and is the first column in the grid, so why it appears at the end I do not know). The AJAX kicks in and the 2nd row is removed. But the grid refreshes odd. It looks like a new column has appeared on the "add" row, which has thrown the other rows and header out.
It is functionally correct, but visually a mess.
NOTE: This also happens when you add a new entry from the "add" row.
FYI - I have followed pieces of Craig Shoemaker's example, however I bind my datasource in the code-behind, amongst other changes. (http://community.infragistics.com/aspnet/articles/webdatagrid-client-side-crud.aspx).
Anyone know what causes this / how to fix it?
Chris,
I tested this and I wasn't able to reproduce this. I would recommend that if you can still reproduce this you post the issue on the Infragistics forums with the code that you are using so that we can look into it further.