araglin
21st December 2008, 00:33
Here is another difficult (for me) thing with using QSortFilterProxyModel.
I have custom Delegate, custom Model, standard QTableView, standard QSortFilterProxyModel.
My custom Delegate provides a widget (based on QDialog) for editing whole row of data at once.
Widget appears on display, user edits LineEdits, then all data is updating. Works well.
But it works only if you don't use sorting. After sorting, rows are lined up in some order, but if we edit a row now, there are some bugs - edited row is dublicated - one with old data and another one with new. I think that's because of incorrect applying of QSortFilterProxyModel. Would you please look at my code to help me find out what's wrong.
main window:
Eve::Eve(QWidget* parent): QMainWindow(parent) {
setupUi(this); readSettings();
eveModel = new EveModel(this);
proxyModel = new QSortFilterProxyModel(this);
proxyModel->setSourceModel(eveModel);
proxyModel->setDynamicSortFilter(true);
tableView->setModel(proxyModel);
header = tableView->horizontalHeader();
header->setModel(eveModel);
eveDelegate = new EveDelegate(this, eveModel, proxyModel);
tableView->setItemDelegate(eveDelegate);
}
void Eve::insertRow() {
eveModel->insertRows(eveModel->rowCount(), 1);
}
void Eve::removeRow() {
eveModel->removeRows(tableView->selectionModel()->currentIndex().row(), 1);
}
Main methods of Delegate:
QWidget *EveDelegate::createEditor ( QWidget *parent,
const QStyleOptionViewItem& option,
const QModelIndex& /* index */ ) const
{
uEditor* editor = new uEditor ( parent ); // my class based on QDialog
return editor;
}
void EveDelegate::setEditorData ( QWidget *e,
const QModelIndex &index ) const
{
// ugly but works
QModelIndex index_sibling0 = index.sibling ( index.row(), 0 ); // Variable
QVariant variable = index_sibling0.model()->data ( index_sibling0, Qt::DisplayRole );
QModelIndex index_sibling1 = index.sibling ( index.row(), 1 ); // Value
QVariant value = index_sibling1.model()->data ( index_sibling1, Qt::DisplayRole );
QModelIndex index_sibling4 = index.sibling ( index.row(), 4 ); // placeToSave
QString placeToSave = index_sibling4.model()->data ( index_sibling4, Qt::DisplayRole ).toString();
uEditor *editor = static_cast<uEditor*> ( e );
editor->valueEdit->setPlainText ( value.toString() );
editor->variableEdit->setText ( variable.toString() );
if( "global" == placeToSave )
editor->checkBox->setChecked(true);
else
editor->checkBox->setChecked(false);
}
void EveDelegate::setModelData (
QWidget *e,
QAbstractItemModel *m,
const QModelIndex& index ) const
{
uEditor *editor = static_cast<uEditor*> ( e );
// getting values from Widget
QString value = editor->valueEdit->toPlainText();
QString variable = editor->variableEdit->text();
QString placeToSave;
if ( editor->checkBox->isChecked() )
placeToSave = "global";
else
placeToSave = "local";
eveModel->setData ( index, variable, value, placeToSave, value );
}
and Model's :
bool EveModel::setData ( const QModelIndex& index,
const QString variable,
const QString value,
const QString placeToSave,
const QString initValue,
int role )
{
if ( index.isValid() )
{
if ( ( *m_records ) [index.row() +1][6].isEmpty() )
( *m_records ) [index.row() +1][6] = ( *m_records ) [index.row() +1][1];
( *m_records ) [index.row() +1][0] = variable;
( *m_records ) [index.row() +1][1] = value;
( *m_records ) [index.row() +1][4] = placeToSave;
emit dataChanged ( index.sibling ( index.row()+1, 0 ), index.sibling ( index.row()+1, 6 ) );
reset();
return true;
}
return false;
}
I have custom Delegate, custom Model, standard QTableView, standard QSortFilterProxyModel.
My custom Delegate provides a widget (based on QDialog) for editing whole row of data at once.
Widget appears on display, user edits LineEdits, then all data is updating. Works well.
But it works only if you don't use sorting. After sorting, rows are lined up in some order, but if we edit a row now, there are some bugs - edited row is dublicated - one with old data and another one with new. I think that's because of incorrect applying of QSortFilterProxyModel. Would you please look at my code to help me find out what's wrong.
main window:
Eve::Eve(QWidget* parent): QMainWindow(parent) {
setupUi(this); readSettings();
eveModel = new EveModel(this);
proxyModel = new QSortFilterProxyModel(this);
proxyModel->setSourceModel(eveModel);
proxyModel->setDynamicSortFilter(true);
tableView->setModel(proxyModel);
header = tableView->horizontalHeader();
header->setModel(eveModel);
eveDelegate = new EveDelegate(this, eveModel, proxyModel);
tableView->setItemDelegate(eveDelegate);
}
void Eve::insertRow() {
eveModel->insertRows(eveModel->rowCount(), 1);
}
void Eve::removeRow() {
eveModel->removeRows(tableView->selectionModel()->currentIndex().row(), 1);
}
Main methods of Delegate:
QWidget *EveDelegate::createEditor ( QWidget *parent,
const QStyleOptionViewItem& option,
const QModelIndex& /* index */ ) const
{
uEditor* editor = new uEditor ( parent ); // my class based on QDialog
return editor;
}
void EveDelegate::setEditorData ( QWidget *e,
const QModelIndex &index ) const
{
// ugly but works
QModelIndex index_sibling0 = index.sibling ( index.row(), 0 ); // Variable
QVariant variable = index_sibling0.model()->data ( index_sibling0, Qt::DisplayRole );
QModelIndex index_sibling1 = index.sibling ( index.row(), 1 ); // Value
QVariant value = index_sibling1.model()->data ( index_sibling1, Qt::DisplayRole );
QModelIndex index_sibling4 = index.sibling ( index.row(), 4 ); // placeToSave
QString placeToSave = index_sibling4.model()->data ( index_sibling4, Qt::DisplayRole ).toString();
uEditor *editor = static_cast<uEditor*> ( e );
editor->valueEdit->setPlainText ( value.toString() );
editor->variableEdit->setText ( variable.toString() );
if( "global" == placeToSave )
editor->checkBox->setChecked(true);
else
editor->checkBox->setChecked(false);
}
void EveDelegate::setModelData (
QWidget *e,
QAbstractItemModel *m,
const QModelIndex& index ) const
{
uEditor *editor = static_cast<uEditor*> ( e );
// getting values from Widget
QString value = editor->valueEdit->toPlainText();
QString variable = editor->variableEdit->text();
QString placeToSave;
if ( editor->checkBox->isChecked() )
placeToSave = "global";
else
placeToSave = "local";
eveModel->setData ( index, variable, value, placeToSave, value );
}
and Model's :
bool EveModel::setData ( const QModelIndex& index,
const QString variable,
const QString value,
const QString placeToSave,
const QString initValue,
int role )
{
if ( index.isValid() )
{
if ( ( *m_records ) [index.row() +1][6].isEmpty() )
( *m_records ) [index.row() +1][6] = ( *m_records ) [index.row() +1][1];
( *m_records ) [index.row() +1][0] = variable;
( *m_records ) [index.row() +1][1] = value;
( *m_records ) [index.row() +1][4] = placeToSave;
emit dataChanged ( index.sibling ( index.row()+1, 0 ), index.sibling ( index.row()+1, 6 ) );
reset();
return true;
}
return false;
}