QCMakeCacheView.cxx 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749
  1. /*=========================================================================
  2. Program: CMake - Cross-Platform Makefile Generator
  3. Module: $RCSfile$
  4. Language: C++
  5. Date: $Date$
  6. Version: $Revision$
  7. Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
  8. See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
  9. This software is distributed WITHOUT ANY WARRANTY; without even
  10. the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  11. PURPOSE. See the above copyright notices for more information.
  12. =========================================================================*/
  13. #include "QCMakeCacheView.h"
  14. #include <QHBoxLayout>
  15. #include <QHeaderView>
  16. #include <QEvent>
  17. #include <QStyle>
  18. #include <QKeyEvent>
  19. #include <QSortFilterProxyModel>
  20. #include "QCMakeWidgets.h"
  21. static QRegExp AdvancedRegExp[2] = { QRegExp("(false)"), QRegExp("(true|false)") };
  22. // filter for searches
  23. class QCMakeSearchFilter : public QSortFilterProxyModel
  24. {
  25. public:
  26. QCMakeSearchFilter(QObject* o) : QSortFilterProxyModel(o) {}
  27. protected:
  28. bool filterAcceptsRow(int row, const QModelIndex& p) const
  29. {
  30. QStringList strs;
  31. const QAbstractItemModel* m = this->sourceModel();
  32. QModelIndex idx = m->index(row, 0, p);
  33. // if there are no children, get strings for column 0 and 1
  34. if(!m->hasChildren(idx))
  35. {
  36. strs.append(m->data(idx).toString());
  37. idx = m->index(row, 1, p);
  38. strs.append(m->data(idx).toString());
  39. }
  40. else
  41. {
  42. // get strings for children entries to compare with
  43. // instead of comparing with the parent
  44. int num = m->rowCount(idx);
  45. for(int i=0; i<num; i++)
  46. {
  47. QModelIndex tmpidx = m->index(i, 0, idx);
  48. strs.append(m->data(tmpidx).toString());
  49. tmpidx = m->index(i, 1, idx);
  50. strs.append(m->data(tmpidx).toString());
  51. }
  52. }
  53. // check all strings for a match
  54. foreach(QString str, strs)
  55. {
  56. if(str.contains(this->filterRegExp()))
  57. {
  58. return true;
  59. }
  60. }
  61. return false;
  62. }
  63. };
  64. QCMakeCacheView::QCMakeCacheView(QWidget* p)
  65. : QTreeView(p), Init(false)
  66. {
  67. // hook up our model and search/filter proxies
  68. this->CacheModel = new QCMakeCacheModel(this);
  69. this->AdvancedFilter = new QSortFilterProxyModel(this);
  70. this->AdvancedFilter->setSourceModel(this->CacheModel);
  71. this->AdvancedFilter->setFilterRole(QCMakeCacheModel::AdvancedRole);
  72. this->AdvancedFilter->setFilterRegExp(AdvancedRegExp[0]);
  73. this->AdvancedFilter->setDynamicSortFilter(true);
  74. this->SearchFilter = new QCMakeSearchFilter(this);
  75. this->SearchFilter->setSourceModel(this->AdvancedFilter);
  76. this->SearchFilter->setFilterCaseSensitivity(Qt::CaseInsensitive);
  77. this->SearchFilter->setDynamicSortFilter(true);
  78. this->setModel(this->SearchFilter);
  79. // our delegate for creating our editors
  80. QCMakeCacheModelDelegate* delegate = new QCMakeCacheModelDelegate(this);
  81. this->setItemDelegate(delegate);
  82. this->setEditTriggers(QAbstractItemView::DoubleClicked |
  83. QAbstractItemView::SelectedClicked |
  84. QAbstractItemView::EditKeyPressed |
  85. QAbstractItemView::AnyKeyPressed);
  86. // tab, backtab doesn't step through items
  87. this->setTabKeyNavigation(false);
  88. // set up headers and sizes
  89. int h = 0;
  90. QFontMetrics met(this->font());
  91. h = qMax(met.height(), this->style()->pixelMetric(QStyle::PM_IndicatorHeight));
  92. this->header()->setDefaultSectionSize(h + 4);
  93. }
  94. void QCMakeCacheView::showEvent(QShowEvent* e)
  95. {
  96. if(!this->Init)
  97. {
  98. // initialize the table view column size
  99. int colWidth = this->columnWidth(0) + this->columnWidth(1);
  100. this->setColumnWidth(0, colWidth/2);
  101. this->setColumnWidth(1, colWidth/2);
  102. this->Init = true;
  103. }
  104. return QTreeView::showEvent(e);
  105. }
  106. QCMakeCacheModel* QCMakeCacheView::cacheModel() const
  107. {
  108. return this->CacheModel;
  109. }
  110. QModelIndex QCMakeCacheView::moveCursor(CursorAction act,
  111. Qt::KeyboardModifiers mod)
  112. {
  113. // want home/end to go to begin/end of rows, not columns
  114. if(act == MoveHome)
  115. {
  116. return this->model()->index(0, 1);
  117. }
  118. else if(act == MoveEnd)
  119. {
  120. return this->model()->index(this->model()->rowCount()-1, 1);
  121. }
  122. return QTreeView::moveCursor(act, mod);
  123. }
  124. void QCMakeCacheView::setShowAdvanced(bool s)
  125. {
  126. #if QT_VERSION >= 040300
  127. // new 4.3 api that needs to be called. what about an older Qt?
  128. this->SearchFilter->invalidate();
  129. #endif
  130. this->AdvancedFilter->setFilterRegExp(
  131. s ? AdvancedRegExp[1] : AdvancedRegExp[0]);
  132. }
  133. bool QCMakeCacheView::showAdvanced() const
  134. {
  135. return this->AdvancedFilter->filterRegExp() == AdvancedRegExp[1];
  136. }
  137. void QCMakeCacheView::setSearchFilter(const QString& s)
  138. {
  139. this->SearchFilter->setFilterFixedString(s);
  140. }
  141. QCMakeCacheModel::QCMakeCacheModel(QObject* p)
  142. : QAbstractItemModel(p),
  143. EditEnabled(true)
  144. {
  145. }
  146. QCMakeCacheModel::~QCMakeCacheModel()
  147. {
  148. }
  149. static uint qHash(const QCMakeProperty& p)
  150. {
  151. return qHash(p.Key);
  152. }
  153. void QCMakeCacheModel::clear()
  154. {
  155. this->setProperties(QCMakePropertyList());
  156. }
  157. void QCMakeCacheModel::setProperties(const QCMakePropertyList& props)
  158. {
  159. QSet<QCMakeProperty> newProps = props.toSet();
  160. QSet<QCMakeProperty> newProps2 = newProps;
  161. QSet<QCMakeProperty> oldProps = this->properties().toSet();
  162. oldProps.intersect(newProps);
  163. newProps.subtract(oldProps);
  164. newProps2.subtract(newProps);
  165. this->Properties.clear();
  166. this->NewProperties.clear();
  167. QMap<QString, QCMakePropertyList> result;
  168. this->breakProperties(newProps, result);
  169. foreach(QString key, result.keys())
  170. {
  171. this->NewProperties.append(QPair<QString, QCMakePropertyList>(key, result.value(key)));
  172. }
  173. result.clear();
  174. this->breakProperties(newProps2, result);
  175. foreach(QString key, result.keys())
  176. {
  177. this->Properties.append(QPair<QString, QCMakePropertyList>(key, result.value(key)));
  178. }
  179. // tell everyone to discard whatever they knew (cached) about this model
  180. this->reset();
  181. }
  182. QString QCMakeCacheModel::prefix(const QString& s)
  183. {
  184. QString prefix = s.section('_', 0, 0);
  185. if(prefix == s)
  186. {
  187. prefix = QString();
  188. }
  189. return prefix;
  190. }
  191. void QCMakeCacheModel::breakProperties(const QSet<QCMakeProperty>& props,
  192. QMap<QString, QCMakePropertyList>& result)
  193. {
  194. QMap<QString, QCMakePropertyList> tmp;
  195. // return a map of properties grouped by prefixes, and sorted
  196. foreach(QCMakeProperty p, props)
  197. {
  198. QString prefix = QCMakeCacheModel::prefix(p.Key);
  199. tmp[prefix].append(p);
  200. }
  201. // sort it and re-org any properties with only one sub item
  202. QCMakePropertyList reorgProps;
  203. QMap<QString, QCMakePropertyList>::iterator iter;
  204. for(iter = tmp.begin(); iter != tmp.end();)
  205. {
  206. if(iter->count() == 1)
  207. {
  208. reorgProps.append((*iter)[0]);
  209. iter = tmp.erase(iter);
  210. }
  211. else
  212. {
  213. qSort(*iter);
  214. ++iter;
  215. }
  216. }
  217. if(reorgProps.count())
  218. {
  219. tmp[QCMakeCacheModel::prefix("NOPREFIX")] += reorgProps;
  220. }
  221. result = tmp;
  222. }
  223. QCMakePropertyList QCMakeCacheModel::properties() const
  224. {
  225. QCMakePropertyList props;
  226. QPair<QString, QCMakePropertyList> l;
  227. foreach(l, this->NewProperties)
  228. {
  229. props += l.second;
  230. }
  231. foreach(l, this->Properties)
  232. {
  233. props += l.second;
  234. }
  235. return props;
  236. }
  237. bool QCMakeCacheModel::insertProperty(QCMakeProperty::PropertyType t,
  238. const QString& name, const QString& description,
  239. const QVariant& value, bool advanced)
  240. {
  241. QCMakeProperty prop;
  242. prop.Key = name;
  243. prop.Value = value;
  244. prop.Help = description;
  245. prop.Type = t;
  246. prop.Advanced = advanced;
  247. // find where to insert it in the new properties section
  248. QString prefix = this->prefix(name);
  249. QList<QPair<QString, QCMakePropertyList> >::iterator iter = this->NewProperties.begin();
  250. while(iter != this->NewProperties.end() && prefix > iter->first)
  251. {
  252. ++iter;
  253. }
  254. bool insertedParent = false;
  255. // insert a new parent item for this group of properties with this prefix
  256. // if there isn't one
  257. if(iter == this->NewProperties.end() || iter->first != prefix)
  258. {
  259. int row = iter - this->NewProperties.begin();
  260. this->beginInsertRows(QModelIndex(), row, row);
  261. iter = this->NewProperties.insert(iter, QPair<QString, QCMakePropertyList>(prefix, QCMakePropertyList()));
  262. insertedParent = true;
  263. }
  264. // find where to insert the property in the group of properties
  265. QCMakePropertyList::iterator jter = iter->second.begin();
  266. while(jter != iter->second.end() && name > jter->Key)
  267. {
  268. ++jter;
  269. }
  270. QModelIndex idxp = this->index(iter - this->NewProperties.begin(), 0);
  271. if(jter != iter->second.end() && jter->Key == name)
  272. {
  273. // replace existing item
  274. *jter = prop;
  275. QModelIndex idx1 = this->index(jter - iter->second.begin(), 0, idxp);
  276. QModelIndex idx2 = this->index(jter - iter->second.begin(), 1, idxp);
  277. this->dataChanged(idx1, idx2);
  278. }
  279. else
  280. {
  281. // add new item
  282. int row = jter - iter->second.begin();
  283. if(!insertedParent)
  284. {
  285. this->beginInsertRows(idxp, row, row);
  286. }
  287. jter = iter->second.insert(jter, prop);
  288. if(!insertedParent)
  289. {
  290. this->endInsertRows();
  291. }
  292. }
  293. if(insertedParent)
  294. {
  295. this->endInsertRows();
  296. }
  297. return true;
  298. }
  299. void QCMakeCacheModel::setEditEnabled(bool e)
  300. {
  301. this->EditEnabled = e;
  302. }
  303. bool QCMakeCacheModel::editEnabled() const
  304. {
  305. return this->EditEnabled;
  306. }
  307. bool QCMakeCacheModel::hasNewProperties() const
  308. {
  309. return !this->NewProperties.isEmpty();
  310. }
  311. int QCMakeCacheModel::columnCount (const QModelIndex& /*p*/ ) const
  312. {
  313. return 2;
  314. }
  315. bool QCMakeCacheModel::isNewProperty(const QModelIndex& idx) const
  316. {
  317. if(idx.isValid() && idx.internalId())
  318. {
  319. return (idx.internalId() - 1) < this->NewProperties.count();
  320. }
  321. else if(idx.isValid())
  322. {
  323. return idx.row() < this->NewProperties.count();
  324. }
  325. return false;
  326. }
  327. const QCMakeProperty* QCMakeCacheModel::propertyForIndex(const QModelIndex& idx) const
  328. {
  329. const QPair<QString, QCMakePropertyList>* l = this->propertyListForIndex(idx);
  330. if(l && idx.internalId())
  331. {
  332. if(idx.row() < l->second.count())
  333. {
  334. return &l->second[idx.row()];
  335. }
  336. }
  337. return NULL;
  338. }
  339. const QPair<QString, QCMakePropertyList>* QCMakeCacheModel::propertyListForIndex(const QModelIndex& idx) const
  340. {
  341. int row = -1;
  342. if(idx.isValid() && idx.internalId() > 0)
  343. {
  344. row = idx.internalId() - 1;
  345. }
  346. else if(idx.isValid())
  347. {
  348. row = idx.row();
  349. }
  350. if(row != -1)
  351. {
  352. if(row < this->NewProperties.count())
  353. {
  354. return &this->NewProperties[row];
  355. }
  356. row -= this->NewProperties.count();
  357. if(row < this->Properties.count())
  358. {
  359. return &this->Properties[row];
  360. }
  361. }
  362. return NULL;
  363. }
  364. QVariant QCMakeCacheModel::data (const QModelIndex& idx, int role) const
  365. {
  366. const QPair<QString, QCMakePropertyList>* l = this->propertyListForIndex(idx);
  367. const QCMakeProperty* p = propertyForIndex(idx);
  368. if(l && !p)
  369. {
  370. if(idx.column() == 0 && (role == Qt::DisplayRole || role == Qt::EditRole))
  371. {
  372. if(l->first == QString())
  373. {
  374. return tr("Ungrouped Entries");
  375. }
  376. return l->first;
  377. }
  378. else if(role == QCMakeCacheModel::AdvancedRole)
  379. {
  380. // return true if all subitems are advanced
  381. foreach(QCMakeProperty p, l->second)
  382. {
  383. if(!p.Advanced)
  384. {
  385. return false;
  386. }
  387. }
  388. return true;
  389. }
  390. }
  391. if(l && p)
  392. {
  393. if(idx.column() == 0 && (role == Qt::DisplayRole || role == Qt::EditRole))
  394. {
  395. return p->Key;
  396. }
  397. else if(idx.column() == 0 && role == Qt::ToolTipRole)
  398. {
  399. return p->Key + "\n" + p->Help;
  400. }
  401. else if(idx.column() == 1 && (role == Qt::DisplayRole || role == Qt::EditRole))
  402. {
  403. if(p->Type != QCMakeProperty::BOOL)
  404. {
  405. return p->Value;
  406. }
  407. }
  408. else if(idx.column() == 1 && role == Qt::CheckStateRole)
  409. {
  410. if(p->Type == QCMakeProperty::BOOL)
  411. {
  412. return p->Value.toBool() ? Qt::Checked : Qt::Unchecked;
  413. }
  414. }
  415. else if(role == QCMakeCacheModel::HelpRole)
  416. {
  417. return p->Help;
  418. }
  419. else if(role == QCMakeCacheModel::TypeRole)
  420. {
  421. return p->Type;
  422. }
  423. else if(role == QCMakeCacheModel::AdvancedRole)
  424. {
  425. return p->Advanced;
  426. }
  427. }
  428. if(role == Qt::BackgroundRole && this->isNewProperty(idx))
  429. {
  430. return QBrush(QColor(255,100,100));
  431. }
  432. return QVariant();
  433. }
  434. QModelIndex QCMakeCacheModel::parent (const QModelIndex& idx) const
  435. {
  436. if(idx.isValid() && idx.internalId())
  437. {
  438. return this->createIndex(idx.internalId()-1, 0);
  439. }
  440. return QModelIndex();
  441. }
  442. QModelIndex QCMakeCacheModel::index (int row, int column, const QModelIndex& idx) const
  443. {
  444. if(!idx.isValid() && row < this->rowCount(idx) && column < this->columnCount(idx))
  445. {
  446. // index at root level
  447. return this->createIndex(row, column);
  448. }
  449. else if(idx.isValid() && !idx.internalId() && row < this->rowCount(idx) && column < this->columnCount(idx))
  450. {
  451. // index at sub-item
  452. return this->createIndex(row, column, idx.row()+1);
  453. }
  454. return QModelIndex();
  455. }
  456. bool QCMakeCacheModel::hasChildren (const QModelIndex& idx) const
  457. {
  458. if(idx.isValid() && idx.internalId())
  459. {
  460. return false;
  461. }
  462. return true;
  463. }
  464. int QCMakeCacheModel::rowCount (const QModelIndex& idx) const
  465. {
  466. if(!idx.isValid())
  467. {
  468. int num = this->Properties.count() + this->NewProperties.count();
  469. return num;
  470. }
  471. const QPair<QString, QCMakePropertyList>* l = this->propertyListForIndex(idx);
  472. const QCMakeProperty* p = this->propertyForIndex(idx);
  473. if(l && !p)
  474. {
  475. return l->second.count();
  476. }
  477. return 0;
  478. }
  479. QVariant QCMakeCacheModel::headerData (int section, Qt::Orientation orient, int role) const
  480. {
  481. // return header labels
  482. if(role == Qt::DisplayRole && orient == Qt::Horizontal)
  483. {
  484. return section == 0 ? "Name" : "Value";
  485. }
  486. return QVariant();
  487. }
  488. Qt::ItemFlags QCMakeCacheModel::flags (const QModelIndex& idx) const
  489. {
  490. Qt::ItemFlags f = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
  491. const QCMakeProperty* p = this->propertyForIndex(idx);
  492. // all column 1's are editable
  493. if(p && idx.column() == 1 && this->EditEnabled)
  494. {
  495. f |= Qt::ItemIsEditable;
  496. // booleans are editable in place
  497. if(p->Type == QCMakeProperty::BOOL)
  498. {
  499. f |= Qt::ItemIsUserCheckable;
  500. }
  501. }
  502. return f;
  503. }
  504. bool QCMakeCacheModel::setData (const QModelIndex& idx, const QVariant& value, int role)
  505. {
  506. QCMakeProperty* p = const_cast<QCMakeProperty*>(this->propertyForIndex(idx));
  507. if(p)
  508. {
  509. if(idx.column() == 1 && (role == Qt::DisplayRole || role == Qt::EditRole))
  510. {
  511. p->Value = value.toString();
  512. emit this->dataChanged(idx, idx);
  513. return true;
  514. }
  515. else if(idx.column() == 1 && (role == Qt::CheckStateRole))
  516. {
  517. p->Value = value.toInt() == Qt::Checked;
  518. emit this->dataChanged(idx, idx);
  519. return true;
  520. }
  521. }
  522. return false;
  523. }
  524. QModelIndex QCMakeCacheModel::buddy(const QModelIndex& idx) const
  525. {
  526. const QCMakeProperty* p = this->propertyForIndex(idx);
  527. if(p && idx.column() == 0)
  528. {
  529. if(p->Type != QCMakeProperty::BOOL)
  530. {
  531. return this->index(idx.row(), 1, idx.parent());
  532. }
  533. }
  534. return idx;
  535. }
  536. bool QCMakeCacheModel::removeRows(int row, int count, const QModelIndex& p)
  537. {
  538. // remove parent items
  539. if(!p.isValid())
  540. {
  541. this->beginRemoveRows(p, row, row-1+count);
  542. while(count != 0 && row < this->NewProperties.count())
  543. {
  544. this->NewProperties.removeAt(row);
  545. count--;
  546. }
  547. row -= this->NewProperties.count();
  548. while(count != 0 && row < this->Properties.count())
  549. {
  550. this->Properties.removeAt(row);
  551. count--;
  552. }
  553. this->endRemoveRows();
  554. return true;
  555. }
  556. // get the parent item containing the item to remove
  557. QPair<QString, QCMakePropertyList>* l =
  558. const_cast<QPair<QString, QCMakePropertyList>*>(this->propertyListForIndex(p));
  559. if(!l || l->second.count() < row)
  560. {
  561. return false;
  562. }
  563. // all items under parent item are being removed, remove the parent item too
  564. if(l->second.count() == count && row == 0)
  565. {
  566. return this->removeRows(p.row(), 1, QModelIndex());
  567. }
  568. // remove the sub items
  569. if(l->second.count() >= count + row)
  570. {
  571. this->beginRemoveRows(p, row, row-1+count);
  572. l->second.erase(l->second.begin()+row, l->second.begin()+row+count);
  573. this->endRemoveRows();
  574. return true;
  575. }
  576. return false;
  577. }
  578. QCMakeCacheModelDelegate::QCMakeCacheModelDelegate(QObject* p)
  579. : QItemDelegate(p), FileDialogFlag(false)
  580. {
  581. }
  582. void QCMakeCacheModelDelegate::setFileDialogFlag(bool f)
  583. {
  584. this->FileDialogFlag = f;
  585. }
  586. QWidget* QCMakeCacheModelDelegate::createEditor(QWidget* p,
  587. const QStyleOptionViewItem&, const QModelIndex& idx) const
  588. {
  589. const QAbstractItemModel* model = idx.model();
  590. QModelIndex var = model->index(idx.row(), 0);
  591. QVariant type = idx.data(QCMakeCacheModel::TypeRole);
  592. if(type == QCMakeProperty::BOOL)
  593. {
  594. return NULL;
  595. }
  596. else if(type == QCMakeProperty::PATH)
  597. {
  598. QCMakePathEditor* editor =
  599. new QCMakePathEditor(p,
  600. var.data(Qt::DisplayRole).toString());
  601. QObject::connect(editor, SIGNAL(fileDialogExists(bool)), this,
  602. SLOT(setFileDialogFlag(bool)));
  603. return editor;
  604. }
  605. else if(type == QCMakeProperty::FILEPATH)
  606. {
  607. QCMakeFilePathEditor* editor =
  608. new QCMakeFilePathEditor(p,
  609. var.data(Qt::DisplayRole).toString());
  610. QObject::connect(editor, SIGNAL(fileDialogExists(bool)), this,
  611. SLOT(setFileDialogFlag(bool)));
  612. return editor;
  613. }
  614. return new QLineEdit(p);
  615. }
  616. bool QCMakeCacheModelDelegate::editorEvent(QEvent* e, QAbstractItemModel* model,
  617. const QStyleOptionViewItem& option, const QModelIndex& index)
  618. {
  619. Qt::ItemFlags flags = model->flags(index);
  620. if (!(flags & Qt::ItemIsUserCheckable) || !(option.state & QStyle::State_Enabled)
  621. || !(flags & Qt::ItemIsEnabled))
  622. {
  623. return false;
  624. }
  625. QVariant value = index.data(Qt::CheckStateRole);
  626. if (!value.isValid())
  627. {
  628. return false;
  629. }
  630. if ((e->type() == QEvent::MouseButtonRelease)
  631. || (e->type() == QEvent::MouseButtonDblClick))
  632. {
  633. // eat the double click events inside the check rect
  634. if (e->type() == QEvent::MouseButtonDblClick)
  635. {
  636. return true;
  637. }
  638. }
  639. else if (e->type() == QEvent::KeyPress)
  640. {
  641. if(static_cast<QKeyEvent*>(e)->key() != Qt::Key_Space &&
  642. static_cast<QKeyEvent*>(e)->key() != Qt::Key_Select)
  643. {
  644. return false;
  645. }
  646. }
  647. else
  648. {
  649. return false;
  650. }
  651. Qt::CheckState state = (static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked
  652. ? Qt::Unchecked : Qt::Checked);
  653. return model->setData(index, state, Qt::CheckStateRole);
  654. }
  655. bool QCMakeCacheModelDelegate::eventFilter(QObject* object, QEvent* event)
  656. {
  657. // workaround for what looks like a bug in Qt on Mac OS X
  658. // where it doesn't create a QWidget wrapper for the native file dialog
  659. // so the Qt library ends up assuming the focus was lost to something else
  660. if(event->type() == QEvent::FocusOut && this->FileDialogFlag)
  661. {
  662. return false;
  663. }
  664. return QItemDelegate::eventFilter(object, event);
  665. }