Changes in table with combo boxes
-
Currently I am testing with this class derived from QTablewidget
header#ifndef MYTABLEWIDGET_H #define MYTABLEWIDGET_H #include <QTableWidget> class MyTableWidget : public QTableWidget { public: MyTableWidget(); void setItem ( int row, int col, const QString & text ); }; #endif // MYTABLEWIDGET_H
Source
#include "MyTableWidget.h" #include "ComboBoxDelegate.h" MyTableWidget::MyTableWidget() { ComboBoxDelegate *vr = new ComboBoxDelegate ( this ); setColumnCount(4); setItemDelegateForColumn ( 1, vr ); setItemDelegateForColumn ( 2, new ComboBoxDelegate ( this ) ); setItemDelegateForColumn ( 3, new ComboBoxDelegate ( this ) ); setRowCount(10); resize(600,400); setItem ( 1, 0, "test 1 0" ); setItem ( 1, 1, "test 1 1" ); setItem ( 1, 2, "test 1 2" ); } void MyTableWidget::setItem ( int row, int col, const QString & text ) { QTableWidget::setItem ( row, col, new QTableWidgetItem ( text ) ); ComboBoxDelegate *vr = qobject_cast < ComboBoxDelegate * > ( this->itemDelegateForColumn ( col ) ); if ( vr ) { vr->addItem ( text, row ); } }
And a main
#include <QApplication> #include "MyTableWidget.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); MyTableWidget tw; tw.show(); return a.exec(); }
-
You probably need to tweak the
setEditorData
method.qobject_cast<QComboBox*>(editor)->setCurrentText(index.model()->data(index, Qt::EditRole).toString());
assumes theindex.data(Qt::EditRole).toString()
is already in the combo box list which might not be the case. change it to:{ auto comboEditor =qobject_cast<QComboBox*>(editor); Q_ASSERT(comboEditor); const QString& textToFind = index.data(Qt::EditRole).toString(); int itemIdx = comboEditor->findText(textToFind); if(itemIdx<0){ comboEditor->addItem(textToFind); itemIdx = comboEditor->findText(textToFind); } Q_ASSERT(itemIdx>=0); comboEditor->setCurrentIndex(itemIdx); }
EDIT fixed compile fail and wrong Q_ASSERT condition
-
Thanks for update.
Unfortunately, the tweaking does not work.
setEditorData
is a const method. Therefore, the compiler complains aboutaddItem
use.Just for completeness. The main tests on my side are on Win 10 and Qt 5.4.2 with MinGW. I have checked it also with Qt 5.9.1 for MinGW. The use of proxy model is always an issue. However, the behaviour is different for both versions.
The major issue is for Qt 5.4.2 that ComboBox entries held are 2 text plus a varying number blank lines at top.
For Qt 5.9.1 it is the opposite. Apparently, two blank lines at the end and varying number of entries at top, but also some are missing.
I am giving up for testing at the time, since my knowledge is not sound enough, yet. Also is the functionality with by-passing of proxy model sufficient for my current use case.However, it is time give the following statements.
Even though I am "complaining" about some deficiencies in your code, I see it more as a feedback in case you need some input.
Your assistance helped significantly improving my speed in getting a workable solution.A huge thanks for turbo-teaching!!
-
@koahnig said in Changes in table with combo boxes:
the compiler complains about addItem use.
you can still copy the entire content of additem in that block or exploit the combo and call
comboEditor->addItem
instead. also, probably it's worth preventing empty (or even whitespace only) strings to be addedThe blank lines are weird. you could check what is going on by inquiring
m_comboProxy->rowCount()
-
Code of
setEditorData
{ auto comboEditor =qobject_cast<QComboBox*>(editor); Q_ASSERT(comboEditor); const QString& textToFind = index.data(Qt::EditRole).toString(); int itemIdx = comboEditor->findText(textToFind); if(itemIdx<0){ comboEditor->addItem(textToFind); itemIdx = comboEditor->findText(textToFind); qDebug() << "addItem " << textToFind << " " << itemIdx << " " << m_comboProxy->rowCount() << " " << m_comboProxy->columnCount(); } Q_ASSERT ( itemIdx >= 0 ); comboEditor->setCurrentIndex(itemIdx); qDebug() << "in combo box " << comboEditor->currentText() << " " << itemIdx << " " << m_comboProxy->rowCount() << " " << m_comboProxy->columnCount();; }
Double click on 4, 2
Typing "Testing" <enter>
Double click on 6, 2
Typing "erf"
Double click 8, 2
Typing "Zufall"output window:
Starting r:\build-AnotherComboBoxTest-Desktop_Qt_5_9_1_MinGW_32bit-Debug\debug\AnotherComboBoxTest.exe... addItem "" 0 2 1 in combo box "" 0 2 1 in combo box "testing" 2 3 1 in combo box "testing" 2 3 1 in combo box "" 0 3 1 in combo box "erf" 1 4 1 in combo box "erf" 1 4 1 in combo box "" 0 4 1 in combo box "" 0 5 1 in combo box "" 0 5 1
That's the outcome
-
Yep, that's what I meant with:
@VRonin said in Changes in table with combo boxes:
also, probably it's worth preventing empty (or even whitespace only) strings
void ComboBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { if (index.data(Qt::EditRole).isNull()) qobject_cast<QComboBox*>(editor)->setCurrentIndex(-1); else { auto comboEditor =qobject_cast<QComboBox*>(editor); Q_ASSERT(comboEditor); const QString& textToFind = index.data(Qt::EditRole).toString(); //make sure you are not just searching whitespace const QRegularExpression realTextRegExp("\S+"); if(!realTextRegExp.match(textToFind).hasMatch()){ comboEditor->setCurrentIndex(-1); return; } int itemIdx = comboEditor->findText(textToFind); if(itemIdx<0){ comboEditor->addItem(textToFind); itemIdx = comboEditor->findText(textToFind); qDebug() << "addItem " << textToFind << " " << itemIdx << " " << m_comboProxy->rowCount() << " " << m_comboProxy->columnCount(); } Q_ASSERT ( itemIdx >= 0 ); comboEditor->setCurrentIndex(itemIdx); qDebug() << "in combo box " << comboEditor->currentText() << " " << itemIdx << " " << m_comboProxy->rowCount() << " " << m_comboProxy->columnCount(); } }
-
I am sorry to correct, but it doesn't help either.
The problem is with the index coming into
setEditorData
Here is my latest code:
void ComboBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { if (index.data(Qt::EditRole).isNull()) qobject_cast<QComboBox*>(editor)->setCurrentIndex(-1); else { auto comboEditor =qobject_cast<QComboBox*>(editor); Q_ASSERT(comboEditor); qDebug() << " index " << index; const QString& textToFind = index.data(Qt::EditRole).toString(); qDebug() << "textToFind before reg exp " << textToFind; //make sure you are not just searching whitespace const QRegularExpression realTextRegExp("\\S+"); if( ! realTextRegExp.match(textToFind).hasMatch()){ qDebug() << "textToFind " << textToFind; comboEditor->setCurrentIndex(-1); return; } int itemIdx = comboEditor->findText(textToFind); if(itemIdx<0){ comboEditor->addItem(textToFind); itemIdx = comboEditor->findText(textToFind); qDebug() << "addItem " << textToFind << " " << itemIdx << " " << m_comboProxy->rowCount() << " " << m_comboProxy->columnCount(); } Q_ASSERT ( itemIdx >= 0 ); comboEditor->setCurrentIndex(itemIdx); qDebug() << "in combo box " << comboEditor->currentText() << " " << itemIdx << " " << m_comboProxy->rowCount() << " " << m_comboProxy->columnCount(); } }
That is the latest output:
Starting r:\build-AnotherComboBoxTest-Desktop_Qt_5_9_1_MinGW_32bit-Debug\debug\AnotherComboBoxTest.exe... no delegate found addItem "test 1 1" E:\Source\AnotherComboBoxTest\MyTableWidget.cpp 28 addItem "test 1 2" E:\Source\AnotherComboBoxTest\MyTableWidget.cpp 28 index QModelIndex(3,1,0x0,QTableModel(0x175fb6a8)) textToFind before reg exp "testing" in combo box "testing" 1 2 1 index QModelIndex(3,1,0x0,QTableModel(0x175fb6a8)) textToFind before reg exp "testing" in combo box "testing" 1 2 1 index QModelIndex(5,1,0x0,QTableModel(0x175fb6a8)) textToFind before reg exp "erf" in combo box "erf" 0 3 1 index QModelIndex(5,1,0x0,QTableModel(0x175fb6a8)) textToFind before reg exp "erf" in combo box "erf" 0 3 1 index QModelIndex(7,1,0x0,QTableModel(0x175fb6a8)) textToFind before reg exp "" textToFind "" index QModelIndex(7,1,0x0,QTableModel(0x175fb6a8)) textToFind before reg exp "" textToFind ""
In additiion the update problems there are also the initial input for this test "test 1 1" not covered anymore after some input directly to the table.
-
-
We are back to the start :(
#define USE_COMBO_PROXY QWidget* ComboBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &) const { QComboBox* result = new QComboBox(parent); result->setEditable( true ); result->setInsertPolicy( QComboBox::InsertAlphabetically ); #ifdef USE_COMBO_PROXY // m_comboProxy->sort( 0 ); result->setModel(m_comboProxy); #else result->setModel(m_comboModel); #endif return result; }
Commenting out
m_comboProxy->sort( 0 )
or by-passing the whole proxy model do work correctly.