title: Calling a Dialog from a ComboBox in a QStyledItemDelegate
body: <p>So what I have here is my delegate code for a <code>QAbstractTableModel</code>. The 2nd column (index = 1), is always a <code>comboBox</code>. That <code>comboBox</code> has a list of actions that a given Unit in my simulation can perform. Upon clicking certain actions like Build or Train, I want a Dialog to pop up giving the user a set of choices. After making there choice, the delegate is supposed to update the model's data and move on.</p>
  
  <p>Here is the snag I've run into. If I try to call a dialog from <code>setModelData()</code>, <code>setEditorData()</code>, those functions are <code>const</code> so I can't <strong>assign</strong> the results of the dialog to anything.</p>
  
  <p>What I have tried to do is to connect the signal <code>indexChanged(QString)</code> from the <code>QComboBox</code> created in <code>createEditor()</code>. This at least allowed me to assign the result and call the dialog only when the appropriate choice was made. However I keep getting a seggy fault and the trace in <code>QTCreator</code> will not land on C code (33 calls of assembly). I'm unsure as to why I got that seggy. </p>
  
  <p>When I tried that approach, the table no longer had the <code>combobox</code> once the dialog appeared. It reverted to its previous state and as soon as the program left the slot I made for <code>QComboBox::indexChanged(QString)</code>, the seggy happened.</p>
  
  <p>DelegateAction.h</p>
  
  <pre><code>#ifndef DELEGATEACTION_H
  #define DELEGATEACTION_H
  
  #include &lt;QVariant&gt;
  #include &lt;QStyledItemDelegate&gt;
  #include &lt;QString&gt;
  
  #include &lt;QApplication&gt;
  #include &lt;QWidget&gt;
  #include &lt;QLabel&gt;
  #include &lt;QComboBox&gt;
  #include &lt;QProgressBar&gt;
  #include &lt;QMouseEvent&gt;
  
  #include &lt;JECMessageTable.h&gt;
  
  #include &lt;UnitBase.h&gt;
  #include &lt;ModelListUnit.h&gt;
  
  class DelegateAction : public QStyledItemDelegate
  {
      Q_OBJECT
  public:
      explicit DelegateAction(QObject *parent = 0);
      ~DelegateAction();
  
      QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &amp;option, const QModelIndex &amp;index) const;
      void setEditorData(QWidget *editor, const QModelIndex &amp;index) const;
      void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &amp;index) const;
      void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &amp;option, const QModelIndex &amp;index) const;
      QSize sizeHint(const QStyleOptionViewItem &amp;option, const QModelIndex &amp;index) const;
  
  public slots:
      void setUnits(QList&lt;Unit*&gt;* units);
  
  protected:
      void paint(QPainter *painter, const QStyleOptionViewItem &amp;option, const QModelIndex &amp;index) const;
      //bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &amp;option, const QModelIndex &amp;index);
  private slots:
      void comboChanged(QString string);
      void comboDestroyed();
  
  private:
      bool comboUpdated;
      const UnitBase* selectedUnit;
      ModelListUnit *model;           // The model for the JECMessageTable.
  
      QList&lt;Unit*&gt;* units;     // The current list of units.
  
  };
  
  #endif // DELEGATEACTION_H
  </code></pre>
  
  <p>DelegateAction.cpp</p>
  
  <pre><code>#include "DelegateAction.h"
  
  DelegateAction::DelegateAction(QObject *parent) :
      QStyledItemDelegate(parent),
      selectedUnit(0),
      model(0)
  {
  }
  
  DelegateAction::~DelegateAction()
  {
      delete model;
  }
  
  QWidget * DelegateAction::createEditor(QWidget *parent, const QStyleOptionViewItem &amp;option, const QModelIndex &amp;index) const
  {
      QWidget* editor = 0;
  
      switch (index.column())
      {
      case 0:
      default:
      {
          editor = new QLabel();
          break;
      }
      case 1:
      {
          QComboBox* combo = new QComboBox(parent);
          combo-&gt;addItem("Idle");
          combo-&gt;addItem("Gather");
          combo-&gt;addItem("Train");
          combo-&gt;addItem("Build");
          combo-&gt;addItem("Upgrade");
          editor = combo;
  //        connect(combo, SIGNAL(currentIndexChanged(QString)), this, SLOT(comboChanged(QString)));
  //        connect(combo, SIGNAL(destroyed()), this, SLOT(comboDestroyed()));
          break;
      }
      case 4:
      {
          editor = new QProgressBar(parent);
          break;
      }
      }
  
      editor-&gt;installEventFilter(const_cast&lt;DelegateAction*&gt;(this));
      return editor;
  }
  
  void DelegateAction::setEditorData(QWidget *editor, const QModelIndex &amp;index) const
  {
      QVariant value = index.model()-&gt;data(index, Qt::DisplayRole);
  
      switch (index.column())
      {
      case 0:
      default:
      {
          QLabel* label = static_cast&lt;QLabel*&gt;(editor);
          label-&gt;setText(value.toString());
          break;
      }
      case 1:
      {
          QComboBox* combo = static_cast&lt;QComboBox*&gt;(editor);
          combo-&gt;setCurrentIndex(combo-&gt;findText(value.toString()));
  
          break;
      }
      case 4:
      {
          QProgressBar* progress = static_cast&lt;QProgressBar*&gt;(editor);
          progress-&gt;setValue(value.toInt());
          break;
      }
      }
  
  }
  
  void DelegateAction::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &amp;index) const
  {
      QVariant value;
      switch (index.column())
      {
      case 0:
      default:
      {
          value = static_cast&lt;QLabel*&gt;(editor)-&gt;text();
          break;
      }
      case 1:
      {
          QString string = static_cast&lt;QComboBox*&gt;(editor)-&gt;currentText();
  
          switch (Action::getType(string))
          {
          case Action::INVALID:
          {
              return;
          }
          case Action::IDLE:
          {
              return;
          }
          case Action::GATHER:
          {
              return;
          }
          case Action::BUILD:
          {
              return;
          }
          case Action::TRAIN:
          {
              // Summon the build choice dialog.
              if (units == 0)
              {
                  return;
              }
  
              JECMessageTable messageBox(this-&gt;model, "Test");
              messageBox.exec();
  
              if (messageBox.result() == QDialog::Accepted)
              {
                  //selectedUnit = this-&gt;model-&gt;getSelectedUnit();
              }
              else
              {
                 //selectedUnit = 0;
              }
  
              return;
          }
          case Action::MORPH:
          {
              return;
          }
          case Action::UPGRADE:
          {
  
          }
          }
  
          break;
      }
      case 4:
      {
          value = static_cast&lt;QProgressBar*&gt;(editor)-&gt;value();
          break;
      }
      }
  
      model-&gt;setData(index, value);
  }
  
  void DelegateAction::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &amp;option, const QModelIndex &amp;index) const
  {
      editor-&gt;setGeometry(option.rect);
  }
  
  QSize DelegateAction::sizeHint(const QStyleOptionViewItem &amp;option, const QModelIndex &amp;index) const
  {
      if (index.column() == 4)
      {
          return QSize(option.rect.width(), option.rect.height());
      }
      else
      {
          return QStyledItemDelegate::sizeHint(option, index);
      }
  }
  
  void DelegateAction::paint(QPainter *painter, const QStyleOptionViewItem &amp;item, const QModelIndex &amp;index) const
  {
      if (index.column() == 4 &amp;&amp; index.isValid() == true)
      {
          QStyleOptionProgressBarV2 progress;
  
          progress.minimum = 0;
          progress.maximum = 100;
          progress.progress = index.data().toInt();
          progress.rect = QRect(item.rect.x(), item.rect.y(), item.rect.width(), item.rect.height());
  
          QApplication::style()-&gt;drawControl(QStyle::CE_ProgressBar, &amp;progress, painter);
      }
      else
      {
          // Painting the cells normally.
          QStyledItemDelegate::paint(painter, item, index);
      }
  }
  
  void DelegateAction::setUnits(QList&lt;Unit*&gt; *units)
  {
      this-&gt;units = units;
  
      if (units != 0)
      {
          if (units-&gt;length() &gt; 0)
          {
              model = new ModelListUnit(&amp;units-&gt;at(0)-&gt;getUnitBase()-&gt;getOptionUnit());
          }
      }
  }
  
  void DelegateAction::comboChanged(QString string)
  {
  
  //    comboUpdated = true;
  //    switch (Action::getType(string))
  //    {
  //    case Action::INVALID:
  //    {
  //        return;
  //    }
  //    case Action::IDLE:
  //    {
  //        return;
  //    }
  //    case Action::GATHER:
  //    {
  //        return;
  //    }
  //    case Action::BUILD:
  //    {
  //        return;
  //    }
  //    case Action::TRAIN:
  //    {
  //        // Summon the build choice dialog.
  //        if (units == 0)
  //        {
  //            return;
  //        }
  
  //        JECMessageTable messageBox(model, "Test");
  //        messageBox.exec();
  
  //        if (messageBox.result() == QDialog::Accepted)
  //        {
  //            selectedUnit = model-&gt;getSelectedUnit();
  //        }
  //        else
  //        {
  //            selectedUnit = 0;
  //        }
  
  //        return;
  //    }
  //    case Action::MORPH:
  //    {
  //        return;
  //    }
  //    case Action::UPGRADE:
  //    {
  
  //    }
  //    }
  
  }
  
  void DelegateAction::comboDestroyed()
  {
      disconnect(this, SLOT(comboChanged(QString)));
      disconnect(this, SLOT(comboDestroyed()));
  }
  
  //bool DelegateAction::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &amp;option, const QModelIndex &amp;index)
  //{
  //    QStyledItemDelegate::editorEvent(event, model, option, index);
  
  //    if (comboUpdated == true &amp;&amp; index.isValid() == true)
  //    {
  //        comboUpdated = false;
  
  //        if (selectedUnit != 0)
  //        {
  //            units-&gt;at(index.row());
  //        }
  //    }
  //}
  </code></pre>