Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

QStyledItemDelegate - How does updateEditorGeometry works?

Tags:

widget

qt

qwidget

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:Screenshot1

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: enter image description here

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!

like image 370
NewbiZ Avatar asked Mar 28 '11 09:03

NewbiZ


1 Answers

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

like image 160
serge_gubenko Avatar answered Sep 19 '22 23:09

serge_gubenko