QCMakeCacheView.cxx 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744
  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. this->AdvancedFilter->setFilterRegExp(
  127. s ? AdvancedRegExp[1] : AdvancedRegExp[0]);
  128. }
  129. bool QCMakeCacheView::showAdvanced() const
  130. {
  131. return this->AdvancedFilter->filterRegExp() == AdvancedRegExp[1];
  132. }
  133. void QCMakeCacheView::setSearchFilter(const QString& s)
  134. {
  135. this->SearchFilter->setFilterFixedString(s);
  136. }
  137. QCMakeCacheModel::QCMakeCacheModel(QObject* p)
  138. : QAbstractItemModel(p),
  139. EditEnabled(true)
  140. {
  141. }
  142. QCMakeCacheModel::~QCMakeCacheModel()
  143. {
  144. }
  145. static uint qHash(const QCMakeProperty& p)
  146. {
  147. return qHash(p.Key);
  148. }
  149. void QCMakeCacheModel::clear()
  150. {
  151. this->setProperties(QCMakePropertyList());
  152. }
  153. void QCMakeCacheModel::setProperties(const QCMakePropertyList& props)
  154. {
  155. QSet<QCMakeProperty> newProps = props.toSet();
  156. QSet<QCMakeProperty> newProps2 = newProps;
  157. QSet<QCMakeProperty> oldProps = this->properties().toSet();
  158. oldProps.intersect(newProps);
  159. newProps.subtract(oldProps);
  160. newProps2.subtract(newProps);
  161. this->Properties.clear();
  162. this->NewProperties.clear();
  163. QMap<QString, QCMakePropertyList> result;
  164. this->breakProperties(newProps, result);
  165. foreach(QString key, result.keys())
  166. {
  167. this->NewProperties.append(QPair<QString, QCMakePropertyList>(key, result.value(key)));
  168. }
  169. result.clear();
  170. this->breakProperties(newProps2, result);
  171. foreach(QString key, result.keys())
  172. {
  173. this->Properties.append(QPair<QString, QCMakePropertyList>(key, result.value(key)));
  174. }
  175. // tell everyone to discard whatever they knew (cached) about this model
  176. this->reset();
  177. }
  178. QString QCMakeCacheModel::prefix(const QString& s)
  179. {
  180. QString prefix = s.section('_', 0, 0);
  181. if(prefix == s)
  182. {
  183. prefix = QString();
  184. }
  185. return prefix;
  186. }
  187. void QCMakeCacheModel::breakProperties(const QSet<QCMakeProperty>& props,
  188. QMap<QString, QCMakePropertyList>& result)
  189. {
  190. QMap<QString, QCMakePropertyList> tmp;
  191. // return a map of properties grouped by prefixes, and sorted
  192. foreach(QCMakeProperty p, props)
  193. {
  194. QString prefix = QCMakeCacheModel::prefix(p.Key);
  195. tmp[prefix].append(p);
  196. }
  197. // sort it and re-org any properties with only one sub item
  198. QCMakePropertyList reorgProps;
  199. QMap<QString, QCMakePropertyList>::iterator iter;
  200. for(iter = tmp.begin(); iter != tmp.end();)
  201. {
  202. if(iter->count() == 1)
  203. {
  204. reorgProps.append((*iter)[0]);
  205. iter = tmp.erase(iter);
  206. }
  207. else
  208. {
  209. qSort(*iter);
  210. ++iter;
  211. }
  212. }
  213. if(reorgProps.count())
  214. {
  215. tmp[QCMakeCacheModel::prefix("NOPREFIX")] += reorgProps;
  216. }
  217. result = tmp;
  218. }
  219. QCMakePropertyList QCMakeCacheModel::properties() const
  220. {
  221. QCMakePropertyList props;
  222. QPair<QString, QCMakePropertyList> l;
  223. foreach(l, this->NewProperties)
  224. {
  225. props += l.second;
  226. }
  227. foreach(l, this->Properties)
  228. {
  229. props += l.second;
  230. }
  231. return props;
  232. }
  233. bool QCMakeCacheModel::insertProperty(QCMakeProperty::PropertyType t,
  234. const QString& name, const QString& description,
  235. const QVariant& value, bool advanced)
  236. {
  237. QCMakeProperty prop;
  238. prop.Key = name;
  239. prop.Value = value;
  240. prop.Help = description;
  241. prop.Type = t;
  242. prop.Advanced = advanced;
  243. // find where to insert it in the new properties section
  244. QString prefix = this->prefix(name);
  245. QList<QPair<QString, QCMakePropertyList> >::iterator iter = this->NewProperties.begin();
  246. while(iter != this->NewProperties.end() && prefix > iter->first)
  247. {
  248. ++iter;
  249. }
  250. bool insertedParent = false;
  251. // insert a new parent item for this group of properties with this prefix
  252. // if there isn't one
  253. if(iter == this->NewProperties.end() || iter->first != prefix)
  254. {
  255. int row = iter - this->NewProperties.begin();
  256. this->beginInsertRows(QModelIndex(), row, row);
  257. iter = this->NewProperties.insert(iter, QPair<QString, QCMakePropertyList>(prefix, QCMakePropertyList()));
  258. insertedParent = true;
  259. }
  260. // find where to insert the property in the group of properties
  261. QCMakePropertyList::iterator jter = iter->second.begin();
  262. while(jter != iter->second.end() && name > jter->Key)
  263. {
  264. ++jter;
  265. }
  266. QModelIndex idxp = this->index(iter - this->NewProperties.begin(), 0);
  267. if(jter != iter->second.end() && jter->Key == name)
  268. {
  269. // replace existing item
  270. *jter = prop;
  271. QModelIndex idx1 = this->index(jter - iter->second.begin(), 0, idxp);
  272. QModelIndex idx2 = this->index(jter - iter->second.begin(), 1, idxp);
  273. this->dataChanged(idx1, idx2);
  274. }
  275. else
  276. {
  277. // add new item
  278. int row = jter - iter->second.begin();
  279. if(!insertedParent)
  280. {
  281. this->beginInsertRows(idxp, row, row);
  282. }
  283. jter = iter->second.insert(jter, prop);
  284. if(!insertedParent)
  285. {
  286. this->endInsertRows();
  287. }
  288. }
  289. if(insertedParent)
  290. {
  291. this->endInsertRows();
  292. }
  293. return true;
  294. }
  295. void QCMakeCacheModel::setEditEnabled(bool e)
  296. {
  297. this->EditEnabled = e;
  298. }
  299. bool QCMakeCacheModel::editEnabled() const
  300. {
  301. return this->EditEnabled;
  302. }
  303. bool QCMakeCacheModel::hasNewProperties() const
  304. {
  305. return !this->NewProperties.isEmpty();
  306. }
  307. int QCMakeCacheModel::columnCount (const QModelIndex& /*p*/ ) const
  308. {
  309. return 2;
  310. }
  311. bool QCMakeCacheModel::isNewProperty(const QModelIndex& idx) const
  312. {
  313. if(idx.isValid() && idx.internalId())
  314. {
  315. return (idx.internalId() - 1) < this->NewProperties.count();
  316. }
  317. else if(idx.isValid())
  318. {
  319. return idx.row() < this->NewProperties.count();
  320. }
  321. return false;
  322. }
  323. const QCMakeProperty* QCMakeCacheModel::propertyForIndex(const QModelIndex& idx) const
  324. {
  325. const QPair<QString, QCMakePropertyList>* l = this->propertyListForIndex(idx);
  326. if(l && idx.internalId())
  327. {
  328. if(idx.row() < l->second.count())
  329. {
  330. return &l->second[idx.row()];
  331. }
  332. }
  333. return NULL;
  334. }
  335. const QPair<QString, QCMakePropertyList>* QCMakeCacheModel::propertyListForIndex(const QModelIndex& idx) const
  336. {
  337. int row = -1;
  338. if(idx.isValid() && idx.internalId() > 0)
  339. {
  340. row = idx.internalId() - 1;
  341. }
  342. else if(idx.isValid())
  343. {
  344. row = idx.row();
  345. }
  346. if(row != -1)
  347. {
  348. if(row < this->NewProperties.count())
  349. {
  350. return &this->NewProperties[row];
  351. }
  352. row -= this->NewProperties.count();
  353. if(row < this->Properties.count())
  354. {
  355. return &this->Properties[row];
  356. }
  357. }
  358. return NULL;
  359. }
  360. QVariant QCMakeCacheModel::data (const QModelIndex& idx, int role) const
  361. {
  362. const QPair<QString, QCMakePropertyList>* l = this->propertyListForIndex(idx);
  363. const QCMakeProperty* p = propertyForIndex(idx);
  364. if(l && !p)
  365. {
  366. if(idx.column() == 0 && (role == Qt::DisplayRole || role == Qt::EditRole))
  367. {
  368. if(l->first == QString())
  369. {
  370. return tr("Ungrouped Properties");
  371. }
  372. return l->first;
  373. }
  374. else if(role == QCMakeCacheModel::AdvancedRole)
  375. {
  376. // return true if all subitems are advanced
  377. foreach(QCMakeProperty p, l->second)
  378. {
  379. if(!p.Advanced)
  380. {
  381. return false;
  382. }
  383. }
  384. return true;
  385. }
  386. }
  387. if(l && p)
  388. {
  389. if(idx.column() == 0 && (role == Qt::DisplayRole || role == Qt::EditRole))
  390. {
  391. return p->Key;
  392. }
  393. else if(idx.column() == 0 && role == Qt::ToolTipRole)
  394. {
  395. return p->Key + "\n" + p->Help;
  396. }
  397. else if(idx.column() == 1 && (role == Qt::DisplayRole || role == Qt::EditRole))
  398. {
  399. if(p->Type != QCMakeProperty::BOOL)
  400. {
  401. return p->Value;
  402. }
  403. }
  404. else if(idx.column() == 1 && role == Qt::CheckStateRole)
  405. {
  406. if(p->Type == QCMakeProperty::BOOL)
  407. {
  408. return p->Value.toBool() ? Qt::Checked : Qt::Unchecked;
  409. }
  410. }
  411. else if(role == QCMakeCacheModel::HelpRole)
  412. {
  413. return p->Help;
  414. }
  415. else if(role == QCMakeCacheModel::TypeRole)
  416. {
  417. return p->Type;
  418. }
  419. else if(role == QCMakeCacheModel::AdvancedRole)
  420. {
  421. return p->Advanced;
  422. }
  423. }
  424. if(role == Qt::BackgroundRole && this->isNewProperty(idx))
  425. {
  426. return QBrush(QColor(255,100,100));
  427. }
  428. return QVariant();
  429. }
  430. QModelIndex QCMakeCacheModel::parent (const QModelIndex& idx) const
  431. {
  432. if(idx.isValid() && idx.internalId())
  433. {
  434. return this->createIndex(idx.internalId()-1, 0);
  435. }
  436. return QModelIndex();
  437. }
  438. QModelIndex QCMakeCacheModel::index (int row, int column, const QModelIndex& idx) const
  439. {
  440. if(!idx.isValid() && row < this->rowCount(idx) && column < this->columnCount(idx))
  441. {
  442. // index at root level
  443. return this->createIndex(row, column);
  444. }
  445. else if(idx.isValid() && !idx.internalId() && row < this->rowCount(idx) && column < this->columnCount(idx))
  446. {
  447. // index at sub-item
  448. return this->createIndex(row, column, idx.row()+1);
  449. }
  450. return QModelIndex();
  451. }
  452. bool QCMakeCacheModel::hasChildren (const QModelIndex& idx) const
  453. {
  454. if(idx.isValid() && idx.internalId())
  455. {
  456. return false;
  457. }
  458. return true;
  459. }
  460. int QCMakeCacheModel::rowCount (const QModelIndex& idx) const
  461. {
  462. if(!idx.isValid())
  463. {
  464. int num = this->Properties.count() + this->NewProperties.count();
  465. return num;
  466. }
  467. const QPair<QString, QCMakePropertyList>* l = this->propertyListForIndex(idx);
  468. const QCMakeProperty* p = this->propertyForIndex(idx);
  469. if(l && !p)
  470. {
  471. return l->second.count();
  472. }
  473. return 0;
  474. }
  475. QVariant QCMakeCacheModel::headerData (int section, Qt::Orientation orient, int role) const
  476. {
  477. // return header labels
  478. if(role == Qt::DisplayRole && orient == Qt::Horizontal)
  479. {
  480. return section == 0 ? "Name" : "Value";
  481. }
  482. return QVariant();
  483. }
  484. Qt::ItemFlags QCMakeCacheModel::flags (const QModelIndex& idx) const
  485. {
  486. Qt::ItemFlags f = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
  487. const QCMakeProperty* p = this->propertyForIndex(idx);
  488. // all column 1's are editable
  489. if(p && idx.column() == 1 && this->EditEnabled)
  490. {
  491. f |= Qt::ItemIsEditable;
  492. // booleans are editable in place
  493. if(p->Type == QCMakeProperty::BOOL)
  494. {
  495. f |= Qt::ItemIsUserCheckable;
  496. }
  497. }
  498. return f;
  499. }
  500. bool QCMakeCacheModel::setData (const QModelIndex& idx, const QVariant& value, int role)
  501. {
  502. QCMakeProperty* p = const_cast<QCMakeProperty*>(this->propertyForIndex(idx));
  503. if(p)
  504. {
  505. if(idx.column() == 1 && (role == Qt::DisplayRole || role == Qt::EditRole))
  506. {
  507. p->Value = value.toString();
  508. emit this->dataChanged(idx, idx);
  509. return true;
  510. }
  511. else if(idx.column() == 1 && (role == Qt::CheckStateRole))
  512. {
  513. p->Value = value.toInt() == Qt::Checked;
  514. emit this->dataChanged(idx, idx);
  515. return true;
  516. }
  517. }
  518. return false;
  519. }
  520. QModelIndex QCMakeCacheModel::buddy(const QModelIndex& idx) const
  521. {
  522. const QCMakeProperty* p = this->propertyForIndex(idx);
  523. if(p && idx.column() == 0)
  524. {
  525. if(p->Type != QCMakeProperty::BOOL)
  526. {
  527. return this->index(idx.row(), 1, idx.parent());
  528. }
  529. }
  530. return idx;
  531. }
  532. bool QCMakeCacheModel::removeRows(int row, int count, const QModelIndex& p)
  533. {
  534. // remove parent items
  535. if(!p.isValid())
  536. {
  537. this->beginRemoveRows(p, row, row-1+count);
  538. while(count != 0 && row < this->NewProperties.count())
  539. {
  540. this->NewProperties.removeAt(row);
  541. count--;
  542. }
  543. row -= this->NewProperties.count();
  544. while(count != 0 && row < this->Properties.count())
  545. {
  546. this->Properties.removeAt(row);
  547. count--;
  548. }
  549. this->endRemoveRows();
  550. return true;
  551. }
  552. // get the parent item containing the item to remove
  553. QPair<QString, QCMakePropertyList>* l =
  554. const_cast<QPair<QString, QCMakePropertyList>*>(this->propertyListForIndex(p));
  555. if(!l || l->second.count() < row)
  556. {
  557. return false;
  558. }
  559. // all items under parent item are being removed, remove the parent item too
  560. if(l->second.count() == count && row == 0)
  561. {
  562. return this->removeRows(p.row(), 1, QModelIndex());
  563. }
  564. // remove the sub items
  565. if(l->second.count() >= count + row)
  566. {
  567. this->beginRemoveRows(p, row, row-1+count);
  568. l->second.erase(l->second.begin()+row, l->second.begin()+row+count);
  569. this->endRemoveRows();
  570. return true;
  571. }
  572. return false;
  573. }
  574. QCMakeCacheModelDelegate::QCMakeCacheModelDelegate(QObject* p)
  575. : QItemDelegate(p), FileDialogFlag(false)
  576. {
  577. }
  578. void QCMakeCacheModelDelegate::setFileDialogFlag(bool f)
  579. {
  580. this->FileDialogFlag = f;
  581. }
  582. QWidget* QCMakeCacheModelDelegate::createEditor(QWidget* p,
  583. const QStyleOptionViewItem&, const QModelIndex& idx) const
  584. {
  585. const QAbstractItemModel* model = idx.model();
  586. QModelIndex var = model->index(idx.row(), 0);
  587. QVariant type = idx.data(QCMakeCacheModel::TypeRole);
  588. if(type == QCMakeProperty::BOOL)
  589. {
  590. return NULL;
  591. }
  592. else if(type == QCMakeProperty::PATH)
  593. {
  594. QCMakePathEditor* editor =
  595. new QCMakePathEditor(p,
  596. var.data(Qt::DisplayRole).toString());
  597. QObject::connect(editor, SIGNAL(fileDialogExists(bool)), this,
  598. SLOT(setFileDialogFlag(bool)));
  599. return editor;
  600. }
  601. else if(type == QCMakeProperty::FILEPATH)
  602. {
  603. QCMakeFilePathEditor* editor =
  604. new QCMakeFilePathEditor(p,
  605. var.data(Qt::DisplayRole).toString());
  606. QObject::connect(editor, SIGNAL(fileDialogExists(bool)), this,
  607. SLOT(setFileDialogFlag(bool)));
  608. return editor;
  609. }
  610. return new QLineEdit(p);
  611. }
  612. bool QCMakeCacheModelDelegate::editorEvent(QEvent* e, QAbstractItemModel* model,
  613. const QStyleOptionViewItem& option, const QModelIndex& index)
  614. {
  615. Qt::ItemFlags flags = model->flags(index);
  616. if (!(flags & Qt::ItemIsUserCheckable) || !(option.state & QStyle::State_Enabled)
  617. || !(flags & Qt::ItemIsEnabled))
  618. {
  619. return false;
  620. }
  621. QVariant value = index.data(Qt::CheckStateRole);
  622. if (!value.isValid())
  623. {
  624. return false;
  625. }
  626. if ((e->type() == QEvent::MouseButtonRelease)
  627. || (e->type() == QEvent::MouseButtonDblClick))
  628. {
  629. // eat the double click events inside the check rect
  630. if (e->type() == QEvent::MouseButtonDblClick)
  631. {
  632. return true;
  633. }
  634. }
  635. else if (e->type() == QEvent::KeyPress)
  636. {
  637. if(static_cast<QKeyEvent*>(e)->key() != Qt::Key_Space &&
  638. static_cast<QKeyEvent*>(e)->key() != Qt::Key_Select)
  639. {
  640. return false;
  641. }
  642. }
  643. else
  644. {
  645. return false;
  646. }
  647. Qt::CheckState state = (static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked
  648. ? Qt::Unchecked : Qt::Checked);
  649. return model->setData(index, state, Qt::CheckStateRole);
  650. }
  651. bool QCMakeCacheModelDelegate::eventFilter(QObject* object, QEvent* event)
  652. {
  653. // workaround for what looks like a bug in Qt on Mac OS X
  654. // where it doesn't create a QWidget wrapper for the native file dialog
  655. // so the Qt library ends up assuming the focus was lost to something else
  656. if(event->type() == QEvent::FocusOut && this->FileDialogFlag)
  657. {
  658. return false;
  659. }
  660. return QItemDelegate::eventFilter(object, event);
  661. }