I'm using Qt 4.7.
I have a model that I display in a QTableView
in two columns, and my goal is to provide inline editing of this model in my QTableView
.
+-----------------+----------------+
| Axis position | Axis range |
+-----------------+----------------+
| Left | Fixed [0,1] |
| Left | Source: SRC1 |
| Right | Source: SRC2 |
| Left | Fixed [5,10] |
+-----------------+----------------+
The first column is editable by using a simple QComboxBox
to switch between Right and Left, and it works quite well. The problem is with my second column, which is editable using a custom widget.
This widget is kind of simple, it describes a range. So there is a QComboBox to select the kind of range ("Fixed": the values are given by the user, "Source": the value are adjusted dynamically from the min/max of a source).
Here is the source code of my custom widget:
class RangeEditor : public QWidget
{
Q_OBJECT
public:
RangeEditor( ... );
~RangeEditor();
public:
CurveView::ConfigAxes::Range range () const;
QVariant minimum() const;
QVariant maximum() const;
DataModel* model () const;
void range ( CurveView::ConfigAxes::Range range );
void minimum( QVariant minimum );
void maximum( QVariant maximum );
void model ( DataModel* model );
public slots:
void rangeTypeChanged( int type );
private: // --- External editors
QComboBox* editRange_;
QSpinBox* editMinimum_;
QSpinBox* editMaximum_;
QComboBox* editModel_;
};
RangeEditor::RangeEditor( ... ) : QWidget(parent)
{
editRange_ = new QComboBox(this);
editMinimum_ = new QSpinBox (this);
editMaximum_ = new QSpinBox (this);
editModel_ = new QComboBox(this);
QHBoxLayout* layout = new QHBoxLayout();
setLayout(layout);
layout->addWidget( editRange_ );
layout->addWidget( editMinimum_ );
layout->addWidget( editMaximum_ );
layout->addWidget( editModel_ );
editRange_->addItem( "Fixed" );
editRange_->addItem( "Source" );
editModel_->setCurrentIndex(0);
editModel_->hide();
QObject::connect( editRange_, SIGNAL(currentIndexChanged(int)),
this, SLOT (rangeTypeChanged(int)) );
}
void RangeEditor::rangeTypeChanged( int type )
{
if ( type==CurveView::ConfigAxes::FIXED )
{
editMinimum_->show();
editMaximum_->show();
editModel_->hide();
}
else if ( type==CurveView::ConfigAxes::SOURCE )
{
editMinimum_->hide();
editMaximum_->hide();
editModel_->show();
}
}
Okay, so now, I created a QStyledItemDelegate to provide the view a custom editor for my columns. Here is how I did it:
class ConfigAxesDelegate : public QStyledItemDelegate
{
public:
ConfigAxesDelegate( ... );
~ConfigAxesDelegate();
public:
virtual QWidget* createEditor ( QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index ) const;
virtual void setEditorData ( QWidget* editor, const QModelIndex& index ) const;
virtual void setModelData ( QWidget* editor, QAbstractItemModel* model, const QModelIndex& index ) const;
virtual void updateEditorGeometry( QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index ) const;
};
QWidget* ConfigAxesDelegate::createEditor( QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
if ( index.column()==0 ) // Position
{
PositionEditor* editor = new PositionEditor(parent);
return editor;
}
else if ( index.column()==1 ) // Range
{
RangeEditor* editor = new RangeEditor(parent);
return editor;
}
else
{
return QStyledItemDelegate::createEditor(parent,option,index);
}
}
void ConfigAxesDelegate::updateEditorGeometry( QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
// WHAT TO DO HERE?
editor->setGeometry( option.rect );
}
Basically, what I get is a single pixel height editor.
Here is a screenshot of the result:
I tried to changed updateEditorGeometry
to the following:
void ConfigAxesDelegate::updateEditorGeometry( QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
QRect r = option.rect;
r.setSize( editor->sizeHint() );
editor->setGeometry( r );
}
Which seems to fix the size problem, but not the position:
I feel kind of lost since I don't know if the problem comes from my custom widget (not providing enough information for Qt to compute its position properly), or the view (maybe some margins that would crush the editor size), or the updateEditorGeometry()
method.
Any help greatly appreciated, thanks for reading!
I would say setting editor's geometry by calling:
editor->setGeometry(rect);
should work correctly; What happens in your case is that your editor is built using QHBoxLayout which has default margins and spacing set. Default height of your tableview rows is less then editor's height and this makes your editor to resize; one pixel row on your screen shot would be: top margin + what's left from controls + bottom margin.
By enabling the vertical header for your tableview you would be able to resize row height to make your editor controls completely visible.
What you could possibly do:
1.Remove\decrease spacing and margins for the layout:
QHBoxLayout* layout = new QHBoxLayout();
layout->setSpacing(1);
layout->setMargin(1);
setLayout(layout);
in this case, updating editor's geometry this way:
QRect rect = option.rect;
QSize sizeHint = editor->sizeHint();
if (rect.width()<sizeHint.width()) rect.setWidth(sizeHint.width());
if (rect.height()<sizeHint.height()) rect.setHeight(sizeHint.height());
editor->setGeometry(rect);
or just
editor->setGeometry(rect);
should work fine for you
2.You can also consider using popup editors for your rows\cells values
3.Resize widget's row heights to fit cell editors.
hope this helps, regards
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With