浏览代码

Use QPersistentModelIndex in ctkCheckbableComboBox

QModelIndex is not meant to be "stored" but used as soon as possible.
In this case, the CheckedList could contain model indexes that are already
deleted.
See http://na-mic.org/Bug/view.php?id=2621
Julien Finet 12 年之前
父节点
当前提交
52cae6da42
共有 1 个文件被更改,包括 60 次插入9 次删除
  1. 60 9
      Libs/Widgets/ctkCheckableComboBox.cpp

+ 60 - 9
Libs/Widgets/ctkCheckableComboBox.cpp

@@ -112,15 +112,24 @@ protected:
   ctkCheckableComboBox* const q_ptr;
   QModelIndexList checkedIndexes()const;
   QModelIndexList uncheckedIndexes()const;
+
 public:
   ctkCheckableComboBoxPrivate(ctkCheckableComboBox& object);
   void init();
 
+  QModelIndexList cachedCheckedIndexes()const;
   void updateCheckedList();
-  
+
   ctkCheckableModelHelper* CheckableModelHelper;
-  QModelIndexList          CheckedList;
-  bool                     MouseButtonPressed;
+  bool MouseButtonPressed;
+
+private:
+  QModelIndexList persistentIndexesToModelIndexes(
+    const QList<QPersistentModelIndex>& persistentModels)const;
+  QList<QPersistentModelIndex> modelIndexesToPersistentIndexes(
+    const QModelIndexList& modelIndexes)const;
+
+  mutable QList<QPersistentModelIndex> CheckedList;
 };
 
 //-----------------------------------------------------------------------------
@@ -150,16 +159,56 @@ void ctkCheckableComboBoxPrivate::init()
 void ctkCheckableComboBoxPrivate::updateCheckedList()
 {
   Q_Q(ctkCheckableComboBox);
-  QModelIndexList newCheckedList = this->checkedIndexes();
-  if (newCheckedList == this->CheckedList)
+  QList<QPersistentModelIndex> newCheckedPersistentList =
+    this->modelIndexesToPersistentIndexes(this->checkedIndexes());
+  if (newCheckedPersistentList == this->CheckedList)
     {
     return;
     }
-  this->CheckedList = newCheckedList;
+  this->CheckedList = newCheckedPersistentList;
   emit q->checkedIndexesChanged();
 }
 
 //-----------------------------------------------------------------------------
+QList<QPersistentModelIndex> ctkCheckableComboBoxPrivate
+::modelIndexesToPersistentIndexes(const QModelIndexList& indexes)const
+{
+  QList<QPersistentModelIndex> res;
+  foreach(const QModelIndex& index, indexes)
+    {
+    QPersistentModelIndex persistent(index);
+    if (persistent.isValid())
+      {
+      res << persistent;
+      }
+    }
+  return res;
+}
+
+//-----------------------------------------------------------------------------
+QModelIndexList ctkCheckableComboBoxPrivate
+::persistentIndexesToModelIndexes(
+  const QList<QPersistentModelIndex>& indexes)const
+{
+  QModelIndexList res;
+  foreach(const QPersistentModelIndex& index, indexes)
+    {
+    if (index.isValid())
+      {
+      res << index;
+      }
+    }
+  return res;
+}
+
+//-----------------------------------------------------------------------------
+QModelIndexList ctkCheckableComboBoxPrivate::cachedCheckedIndexes()const
+{
+  Q_Q(const ctkCheckableComboBox);
+  return this->persistentIndexesToModelIndexes(this->CheckedList);
+}
+
+//-----------------------------------------------------------------------------
 QModelIndexList ctkCheckableComboBoxPrivate::checkedIndexes()const
 {
   Q_Q(const ctkCheckableComboBox);
@@ -266,7 +315,7 @@ QAbstractItemModel* ctkCheckableComboBox::checkableModel()const
 QModelIndexList ctkCheckableComboBox::checkedIndexes()const
 {
   Q_D(const ctkCheckableComboBox);
-  return d->CheckedList;
+  return d->cachedCheckedIndexes();
 }
 
 //-----------------------------------------------------------------------------
@@ -280,7 +329,7 @@ bool ctkCheckableComboBox::allChecked()const
 bool ctkCheckableComboBox::noneChecked()const
 {
   Q_D(const ctkCheckableComboBox);
-  return d->CheckedList.count() == 0;
+  return d->cachedCheckedIndexes().count() == 0;
 }
 
 //-----------------------------------------------------------------------------
@@ -309,6 +358,8 @@ void ctkCheckableComboBox::onDataChanged(const QModelIndex& start, const QModelI
 //-----------------------------------------------------------------------------
 void ctkCheckableComboBox::paintEvent(QPaintEvent *)
 {
+  Q_D(ctkCheckableComboBox);
+
   QStylePainter painter(this);
   painter.setPen(palette().color(QPalette::Text));
 
@@ -329,7 +380,7 @@ void ctkCheckableComboBox::paintEvent(QPaintEvent *)
   else
     {
     //search the checked items
-    QModelIndexList indexes = this->checkedIndexes();
+    QModelIndexList indexes = d->cachedCheckedIndexes();
     if (indexes.count() == 1)
       {
       opt.currentText = this->model()->data(indexes[0], Qt::DisplayRole).toString();