title: Qt - QTreeView and custom model with checkbox columns
body: <p>I wanted to have a tree view which shows the item name, the item description, and two related Boolean values in respective columns. I started by modifying the <a href="http://doc.qt.io/qt-5/qtwidgets-itemviews-editabletreemodel-example.html" rel="nofollow noreferrer">Editable Tree Mode example</a>, so there's a TreeModel that keeps track of a group of TreeItems, each of which not only has a list of child TreeItems, but also a list of QVariants which stores a set of values that can later be displayed in columns in the QTreeView.</p>
  
  <p>I managed to add two more columns for two Boolean values. I also searched through the net on how to add checkboxes for QTreeView and QAbstractItemModel. I managed to have the checkboxes on the two Boolean columns working okay, as well as the rest of the tree hierarchy. Yet all the items in each column renders a checkbox and a line of text now. </p>
  
  <p><a href="https://i.stack.imgur.com/Wpvbt.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/Wpvbt.jpg" alt="Qt TreeView with Checkboxes"></a></p>
  
  <p>Here's the parts where I've modified from the example, mainly within TreeModel.</p>
  
  <p><strong>treemodel.cpp:</strong></p>
  
  <pre><code>bool TreeModel::isBooleanColumn( const QModelIndex &amp;index ) const
  {
      bool bRet = false;
      if ( !index.isValid() )
      {
      }
      else
      {
          bRet = ( index.column() == COLUMN_BOL1 ) || ( index.column() == COLUMN_ BOL2 );
      }
      return bRet;
  }
  
  Qt::ItemFlags TreeModel::flags(const QModelIndex &amp;index) const
  {
      if (!index.isValid())
          return 0;
      if ( isBooleanColumn( index ) )
      {
          return Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
      }
      else
      {
          return Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
      }
  }
  
  QVariant TreeModel::data(const QModelIndex &amp;index, int role) const
  {
      if (!index.isValid())
          return QVariant();
      if (role != Qt::DisplayRole &amp;&amp; role != Qt::EditRole &amp;&amp; role != Qt::CheckStateRole )
          return QVariant();
      TreeItem *item = getItem(index);
      if ( role == Qt::CheckStateRole &amp;&amp; isBooleanColumn( index ) )
      {
          Qt::CheckState eChkState = ( item-&gt;data( index.column() ).toBool() ) ? Qt::Checked : Qt::Unchecked;
          return eChkState;
      }
      return item-&gt;data(index.column());
  }
  
  bool TreeModel::setData(const QModelIndex &amp;index, const QVariant &amp;value,
                          int role)
  {
      if (role != Qt::EditRole &amp;&amp; role != Qt::CheckStateRole )
          return false;
      TreeItem *item = getItem(index);
      bool result;
      if ( role == Qt::CheckStateRole &amp;&amp; isBooleanColumn( index ) )
      {
          Qt::CheckState eChecked = static_cast&lt; Qt::CheckState &gt;( value.toInt() );
          bool bNewValue = eChecked == Qt::Checked;
          result = item-&gt;setData( index.column(), bNewValue );
      }
      else
      {
          result = item-&gt;setData(index.column(), value);
      }
      if (result)
          emit dataChanged(index, index);
      return result;
  }
  </code></pre>
  
  <p><strong>mainwindow.cpp:</strong></p>
  
  <pre><code>MainWindow::MainWindow(QWidget *parent)
  : QMainWindow(parent)
  {
      …
      QStringList headers;
      headers &lt;&lt; tr("Title") &lt;&lt; tr("Description") &lt;&lt; tr("Hide") &lt;&lt; tr("Lock");
      QFile file(":/default.txt");
      file.open(QIODevice::ReadOnly);
      TreeModel *model = new TreeModel(headers, file.readAll());
      file.close();
  
      …
  }
  </code></pre>
  
  <p>The checkboxes under the non-Boolean columns don't respond to user input, and the text under the Boolean columns aren't editable. So functionality-wise there's nothing wrong, but it's still bothersome as far as UI goes.</p>
  
  <p>I'm moving onto having QTreeWidget do the same thing. Meanwhile, I'm couldn't help but wonder if there's something else I'm missing here. I heard one solution is to have a custom delegate; is that the only option?</p>
  
  <p>If there's anyone who can point out what else I need to do, or provide a similar example, I will greatly appreciate it.</p>