QCMakeCacheView.cxx 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  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 <QToolButton>
  15. #include <QFileDialog>
  16. #include <QHBoxLayout>
  17. #include <QHeaderView>
  18. #include <QEvent>
  19. #include <QFileInfo>
  20. #include <QStyle>
  21. #include <QKeyEvent>
  22. static QRegExp AdvancedRegExp[2] = { QRegExp("(false)"), QRegExp("(true|false)") };
  23. QCMakeCacheView::QCMakeCacheView(QWidget* p)
  24. : QTableView(p), Init(false)
  25. {
  26. // hook up our model and search/filter proxies
  27. this->CacheModel = new QCMakeCacheModel(this);
  28. this->AdvancedFilter = new QSortFilterProxyModel(this);
  29. this->AdvancedFilter->setSourceModel(this->CacheModel);
  30. this->AdvancedFilter->setFilterRole(QCMakeCacheModel::AdvancedRole);
  31. this->AdvancedFilter->setFilterRegExp(AdvancedRegExp[0]);
  32. this->SearchFilter = new QSortFilterProxyModel(this);
  33. this->SearchFilter->setSourceModel(this->AdvancedFilter);
  34. this->setModel(this->SearchFilter);
  35. // our delegate for creating our editors
  36. QCMakeCacheModelDelegate* delegate = new QCMakeCacheModelDelegate(this);
  37. this->setItemDelegate(delegate);
  38. // set up headers and sizes
  39. int h = 0;
  40. QFontMetrics met(this->font());
  41. h = qMax(met.height(), this->style()->pixelMetric(QStyle::PM_IndicatorHeight));
  42. this->verticalHeader()->setDefaultSectionSize(h + 4);
  43. this->horizontalHeader()->setStretchLastSection(true);
  44. this->verticalHeader()->hide();
  45. }
  46. void QCMakeCacheView::showEvent(QShowEvent* e)
  47. {
  48. if(!this->Init)
  49. {
  50. // initialize the table view column size
  51. int colWidth = this->columnWidth(0) + this->columnWidth(1);
  52. this->setColumnWidth(0, colWidth/2);
  53. this->setColumnWidth(1, colWidth/2);
  54. this->Init = true;
  55. }
  56. return QTableView::showEvent(e);
  57. }
  58. QCMakeCacheModel* QCMakeCacheView::cacheModel() const
  59. {
  60. return this->CacheModel;
  61. }
  62. QModelIndex QCMakeCacheView::moveCursor(CursorAction act,
  63. Qt::KeyboardModifiers mod)
  64. {
  65. // tab through values only (not names)
  66. QModelIndex current = this->currentIndex();
  67. if(act == MoveNext)
  68. {
  69. if(!current.isValid())
  70. {
  71. return this->model()->index(0, 1);
  72. }
  73. else if(current.column() == 0)
  74. {
  75. return this->model()->index(current.row(), 1);
  76. }
  77. else
  78. {
  79. return this->model()->index(current.row()+1, 1);
  80. }
  81. }
  82. else if(act == MovePrevious)
  83. {
  84. if(!current.isValid())
  85. {
  86. return this->model()->index(0, 1);
  87. }
  88. else
  89. {
  90. return this->model()->index(current.row()-1, 1);
  91. }
  92. }
  93. return QTableView::moveCursor(act, mod);
  94. }
  95. void QCMakeCacheView::setShowAdvanced(bool s)
  96. {
  97. this->AdvancedFilter->setFilterRegExp(
  98. s ? AdvancedRegExp[1] : AdvancedRegExp[0]);
  99. }
  100. bool QCMakeCacheView::showAdvanced() const
  101. {
  102. return this->AdvancedFilter->filterRegExp() == AdvancedRegExp[1];
  103. }
  104. void QCMakeCacheView::setSearchFilter(const QString& s)
  105. {
  106. this->SearchFilter->setFilterRegExp(s);
  107. }
  108. QCMakeCacheModel::QCMakeCacheModel(QObject* p)
  109. : QAbstractTableModel(p), NewCount(0), IsDirty(false)
  110. {
  111. }
  112. QCMakeCacheModel::~QCMakeCacheModel()
  113. {
  114. }
  115. bool QCMakeCacheModel::isDirty() const
  116. {
  117. return this->IsDirty;
  118. }
  119. static uint qHash(const QCMakeCacheProperty& p)
  120. {
  121. return qHash(p.Key);
  122. }
  123. void QCMakeCacheModel::clear()
  124. {
  125. this->setProperties(QCMakeCachePropertyList());
  126. }
  127. void QCMakeCacheModel::setProperties(const QCMakeCachePropertyList& props)
  128. {
  129. QSet<QCMakeCacheProperty> newProps = props.toSet();
  130. QSet<QCMakeCacheProperty> oldProps = this->Properties.toSet();
  131. oldProps.intersect(newProps);
  132. newProps.subtract(oldProps);
  133. this->NewCount = newProps.count();
  134. this->Properties.clear();
  135. this->Properties = newProps.toList();
  136. qSort(this->Properties);
  137. QCMakeCachePropertyList tmp = oldProps.toList();
  138. qSort(tmp);
  139. this->Properties += tmp;
  140. this->reset();
  141. this->IsDirty = false;
  142. }
  143. QCMakeCachePropertyList QCMakeCacheModel::properties() const
  144. {
  145. return this->Properties;
  146. }
  147. int QCMakeCacheModel::columnCount (const QModelIndex& /*p*/ ) const
  148. {
  149. return 2;
  150. }
  151. QVariant QCMakeCacheModel::data (const QModelIndex& idx, int role) const
  152. {
  153. if(idx.column() == 0 && (role == Qt::DisplayRole || role == Qt::EditRole))
  154. {
  155. return this->Properties[idx.row()].Key;
  156. }
  157. else if(idx.column() == 0 && role == Qt::ToolTipRole)
  158. {
  159. return this->data(idx, Qt::DisplayRole).toString() + "\n" +
  160. this->data(idx, QCMakeCacheModel::HelpRole).toString();
  161. }
  162. else if(idx.column() == 1 && (role == Qt::DisplayRole || role == Qt::EditRole))
  163. {
  164. if(this->Properties[idx.row()].Type != QCMakeCacheProperty::BOOL)
  165. {
  166. return this->Properties[idx.row()].Value;
  167. }
  168. }
  169. else if(idx.column() == 1 && role == Qt::CheckStateRole)
  170. {
  171. if(this->Properties[idx.row()].Type == QCMakeCacheProperty::BOOL)
  172. {
  173. return this->Properties[idx.row()].Value.toBool() ? Qt::Checked : Qt::Unchecked;
  174. }
  175. }
  176. else if(role == QCMakeCacheModel::HelpRole)
  177. {
  178. return this->Properties[idx.row()].Help;
  179. }
  180. else if(role == QCMakeCacheModel::TypeRole)
  181. {
  182. return this->Properties[idx.row()].Type;
  183. }
  184. else if(role == QCMakeCacheModel::AdvancedRole)
  185. {
  186. return this->Properties[idx.row()].Advanced;
  187. }
  188. else if(role == Qt::BackgroundRole && idx.row()+1 <= this->NewCount)
  189. {
  190. return QBrush(QColor(255,100,100));
  191. }
  192. return QVariant();
  193. }
  194. QModelIndex QCMakeCacheModel::parent (const QModelIndex& /*idx*/) const
  195. {
  196. return QModelIndex();
  197. }
  198. int QCMakeCacheModel::rowCount (const QModelIndex& p) const
  199. {
  200. if(p.isValid())
  201. {
  202. return 0;
  203. }
  204. return this->Properties.count();
  205. }
  206. QVariant QCMakeCacheModel::headerData (int section, Qt::Orientation orient, int role) const
  207. {
  208. // return header labels
  209. if(role == Qt::DisplayRole && orient == Qt::Horizontal)
  210. {
  211. return section == 0 ? "Name" : "Value";
  212. }
  213. return QVariant();
  214. }
  215. Qt::ItemFlags QCMakeCacheModel::flags (const QModelIndex& idx) const
  216. {
  217. Qt::ItemFlags f = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
  218. // all column 1's are editable
  219. if(idx.column() == 1)
  220. {
  221. f |= Qt::ItemIsEditable;
  222. // booleans are editable in place
  223. if(this->Properties[idx.row()].Type == QCMakeCacheProperty::BOOL)
  224. {
  225. f |= Qt::ItemIsUserCheckable;
  226. }
  227. }
  228. return f;
  229. }
  230. bool QCMakeCacheModel::setData (const QModelIndex& idx, const QVariant& value, int role)
  231. {
  232. if(idx.column() == 0 && (role == Qt::DisplayRole || role == Qt::EditRole))
  233. {
  234. this->Properties[idx.row()].Key = value.toString();
  235. this->IsDirty = true;
  236. emit this->dataChanged(idx, idx);
  237. }
  238. else if(idx.column() == 1 && (role == Qt::DisplayRole || role == Qt::EditRole))
  239. {
  240. this->Properties[idx.row()].Value = value.toString();
  241. this->IsDirty = true;
  242. emit this->dataChanged(idx, idx);
  243. }
  244. else if(idx.column() == 1 && (role == Qt::CheckStateRole))
  245. {
  246. this->Properties[idx.row()].Value = value.toInt() == Qt::Checked;
  247. this->IsDirty = true;
  248. emit this->dataChanged(idx, idx);
  249. }
  250. return false;
  251. }
  252. QCMakeCacheModelDelegate::QCMakeCacheModelDelegate(QObject* p)
  253. : QItemDelegate(p)
  254. {
  255. }
  256. QWidget* QCMakeCacheModelDelegate::createEditor(QWidget* p,
  257. const QStyleOptionViewItem&, const QModelIndex& idx) const
  258. {
  259. QVariant type = idx.data(QCMakeCacheModel::TypeRole);
  260. if(type == QCMakeCacheProperty::BOOL)
  261. {
  262. return NULL;
  263. }
  264. else if(type == QCMakeCacheProperty::PATH)
  265. {
  266. return new QCMakeCachePathEditor(idx.data().toString(), false, p);
  267. }
  268. else if(type == QCMakeCacheProperty::FILEPATH)
  269. {
  270. return new QCMakeCachePathEditor(idx.data().toString(), true, p);
  271. }
  272. return new QLineEdit(p);
  273. }
  274. QCMakeCachePathEditor::QCMakeCachePathEditor(const QString& file, bool fp,
  275. QWidget* p)
  276. : QWidget(p), LineEdit(this), IsFilePath(fp)
  277. {
  278. QHBoxLayout* l = new QHBoxLayout(this);
  279. l->setMargin(0);
  280. l->setSpacing(0);
  281. l->addWidget(&this->LineEdit);
  282. QToolButton* tb = new QToolButton(this);
  283. tb->setText("...");
  284. l->addWidget(tb);
  285. QObject::connect(tb, SIGNAL(clicked(bool)),
  286. this, SLOT(chooseFile()));
  287. this->LineEdit.setText(file);
  288. this->LineEdit.selectAll();
  289. tb->setFocusProxy(&this->LineEdit);
  290. this->setFocusProxy(&this->LineEdit);
  291. }
  292. void QCMakeCachePathEditor::chooseFile()
  293. {
  294. QString path;
  295. if(this->IsFilePath)
  296. {
  297. QFileInfo info(this->value());
  298. path = QFileDialog::getOpenFileName(this, tr("Select File"),
  299. info.absolutePath());
  300. }
  301. else
  302. {
  303. path = QFileDialog::getExistingDirectory(this, tr("Select Path"),
  304. this->value());
  305. }
  306. if(!path.isEmpty())
  307. {
  308. this->LineEdit.setText(path);
  309. }
  310. }