mirror of
https://github.com/reactos/CMake.git
synced 2024-12-14 23:29:57 +00:00
86578eccf2
Per-source copyright/license notice headers that spell out copyright holder names and years are hard to maintain and often out-of-date or plain wrong. Precise contributor information is already maintained automatically by the version control tool. Ultimately it is the receiver of a file who is responsible for determining its licensing status, and per-source notices are merely a convenience. Therefore it is simpler and more accurate for each source to have a generic notice of the license name and references to more detailed information on copyright holders and full license terms. Our `Copyright.txt` file now contains a list of Contributors whose names appeared source-level copyright notices. It also references version control history for more precise information. Therefore we no longer need to spell out the list of Contributors in each source file notice. Replace CMake per-source copyright/license notice headers with a short description of the license and links to `Copyright.txt` and online information available from "https://cmake.org/licensing". The online URL also handles cases of modules being copied out of our source into other projects, so we can drop our notices about replacing links with full license text. Run the `Utilities/Scripts/filter-notices.bash` script to perform the majority of the replacements mechanically. Manually fix up shebang lines and trailing newlines in a few files. Manually update the notices in a few files that the script does not handle.
679 lines
19 KiB
C++
679 lines
19 KiB
C++
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
|
file Copyright.txt or https://cmake.org/licensing for details. */
|
|
#include "QCMakeCacheView.h"
|
|
|
|
#include <QApplication>
|
|
#include <QEvent>
|
|
#include <QHBoxLayout>
|
|
#include <QHeaderView>
|
|
#include <QKeyEvent>
|
|
#include <QMetaProperty>
|
|
#include <QSortFilterProxyModel>
|
|
#include <QStyle>
|
|
|
|
#include "QCMakeWidgets.h"
|
|
|
|
// filter for searches
|
|
class QCMakeSearchFilter : public QSortFilterProxyModel
|
|
{
|
|
public:
|
|
QCMakeSearchFilter(QObject* o)
|
|
: QSortFilterProxyModel(o)
|
|
{
|
|
}
|
|
|
|
protected:
|
|
bool filterAcceptsRow(int row, const QModelIndex& p) const CM_OVERRIDE
|
|
{
|
|
QStringList strs;
|
|
const QAbstractItemModel* m = this->sourceModel();
|
|
QModelIndex idx = m->index(row, 0, p);
|
|
|
|
// if there are no children, get strings for column 0 and 1
|
|
if (!m->hasChildren(idx)) {
|
|
strs.append(m->data(idx).toString());
|
|
idx = m->index(row, 1, p);
|
|
strs.append(m->data(idx).toString());
|
|
} else {
|
|
// get strings for children entries to compare with
|
|
// instead of comparing with the parent
|
|
int num = m->rowCount(idx);
|
|
for (int i = 0; i < num; i++) {
|
|
QModelIndex tmpidx = m->index(i, 0, idx);
|
|
strs.append(m->data(tmpidx).toString());
|
|
tmpidx = m->index(i, 1, idx);
|
|
strs.append(m->data(tmpidx).toString());
|
|
}
|
|
}
|
|
|
|
// check all strings for a match
|
|
foreach (QString str, strs) {
|
|
if (str.contains(this->filterRegExp())) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
};
|
|
|
|
// filter for searches
|
|
class QCMakeAdvancedFilter : public QSortFilterProxyModel
|
|
{
|
|
public:
|
|
QCMakeAdvancedFilter(QObject* o)
|
|
: QSortFilterProxyModel(o)
|
|
, ShowAdvanced(false)
|
|
{
|
|
}
|
|
|
|
void setShowAdvanced(bool f)
|
|
{
|
|
this->ShowAdvanced = f;
|
|
this->invalidate();
|
|
}
|
|
bool showAdvanced() const { return this->ShowAdvanced; }
|
|
|
|
protected:
|
|
bool ShowAdvanced;
|
|
|
|
bool filterAcceptsRow(int row, const QModelIndex& p) const CM_OVERRIDE
|
|
{
|
|
const QAbstractItemModel* m = this->sourceModel();
|
|
QModelIndex idx = m->index(row, 0, p);
|
|
|
|
// if there are no children
|
|
if (!m->hasChildren(idx)) {
|
|
bool adv = m->data(idx, QCMakeCacheModel::AdvancedRole).toBool();
|
|
return !adv || this->ShowAdvanced;
|
|
}
|
|
|
|
// check children
|
|
int num = m->rowCount(idx);
|
|
for (int i = 0; i < num; i++) {
|
|
bool accept = this->filterAcceptsRow(i, idx);
|
|
if (accept) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
};
|
|
|
|
QCMakeCacheView::QCMakeCacheView(QWidget* p)
|
|
: QTreeView(p)
|
|
{
|
|
// hook up our model and search/filter proxies
|
|
this->CacheModel = new QCMakeCacheModel(this);
|
|
this->AdvancedFilter = new QCMakeAdvancedFilter(this);
|
|
this->AdvancedFilter->setSourceModel(this->CacheModel);
|
|
this->AdvancedFilter->setDynamicSortFilter(true);
|
|
this->SearchFilter = new QCMakeSearchFilter(this);
|
|
this->SearchFilter->setSourceModel(this->AdvancedFilter);
|
|
this->SearchFilter->setFilterCaseSensitivity(Qt::CaseInsensitive);
|
|
this->SearchFilter->setDynamicSortFilter(true);
|
|
this->setModel(this->SearchFilter);
|
|
|
|
// our delegate for creating our editors
|
|
QCMakeCacheModelDelegate* delegate = new QCMakeCacheModelDelegate(this);
|
|
this->setItemDelegate(delegate);
|
|
|
|
this->setUniformRowHeights(true);
|
|
|
|
this->setEditTriggers(QAbstractItemView::AllEditTriggers);
|
|
|
|
// tab, backtab doesn't step through items
|
|
this->setTabKeyNavigation(false);
|
|
|
|
this->setRootIsDecorated(false);
|
|
}
|
|
|
|
bool QCMakeCacheView::event(QEvent* e)
|
|
{
|
|
if (e->type() == QEvent::Show) {
|
|
this->header()->setDefaultSectionSize(this->viewport()->width() / 2);
|
|
}
|
|
return QTreeView::event(e);
|
|
}
|
|
|
|
QCMakeCacheModel* QCMakeCacheView::cacheModel() const
|
|
{
|
|
return this->CacheModel;
|
|
}
|
|
|
|
QModelIndex QCMakeCacheView::moveCursor(CursorAction act,
|
|
Qt::KeyboardModifiers mod)
|
|
{
|
|
// want home/end to go to begin/end of rows, not columns
|
|
if (act == MoveHome) {
|
|
return this->model()->index(0, 1);
|
|
}
|
|
if (act == MoveEnd) {
|
|
return this->model()->index(this->model()->rowCount() - 1, 1);
|
|
}
|
|
return QTreeView::moveCursor(act, mod);
|
|
}
|
|
|
|
void QCMakeCacheView::setShowAdvanced(bool s)
|
|
{
|
|
#if QT_VERSION >= 040300
|
|
// new 4.3 API that needs to be called. what about an older Qt?
|
|
this->SearchFilter->invalidate();
|
|
#endif
|
|
|
|
this->AdvancedFilter->setShowAdvanced(s);
|
|
}
|
|
|
|
bool QCMakeCacheView::showAdvanced() const
|
|
{
|
|
return this->AdvancedFilter->showAdvanced();
|
|
}
|
|
|
|
void QCMakeCacheView::setSearchFilter(const QString& s)
|
|
{
|
|
this->SearchFilter->setFilterFixedString(s);
|
|
}
|
|
|
|
QCMakeCacheModel::QCMakeCacheModel(QObject* p)
|
|
: QStandardItemModel(p)
|
|
, EditEnabled(true)
|
|
, NewPropertyCount(0)
|
|
, View(FlatView)
|
|
{
|
|
this->ShowNewProperties = true;
|
|
QStringList labels;
|
|
labels << tr("Name") << tr("Value");
|
|
this->setHorizontalHeaderLabels(labels);
|
|
}
|
|
|
|
QCMakeCacheModel::~QCMakeCacheModel()
|
|
{
|
|
}
|
|
|
|
static uint qHash(const QCMakeProperty& p)
|
|
{
|
|
return qHash(p.Key);
|
|
}
|
|
|
|
void QCMakeCacheModel::setShowNewProperties(bool f)
|
|
{
|
|
this->ShowNewProperties = f;
|
|
}
|
|
|
|
void QCMakeCacheModel::clear()
|
|
{
|
|
this->QStandardItemModel::clear();
|
|
this->NewPropertyCount = 0;
|
|
|
|
QStringList labels;
|
|
labels << tr("Name") << tr("Value");
|
|
this->setHorizontalHeaderLabels(labels);
|
|
}
|
|
|
|
void QCMakeCacheModel::setProperties(const QCMakePropertyList& props)
|
|
{
|
|
QSet<QCMakeProperty> newProps, newProps2;
|
|
|
|
if (this->ShowNewProperties) {
|
|
newProps = props.toSet();
|
|
newProps2 = newProps;
|
|
QSet<QCMakeProperty> oldProps = this->properties().toSet();
|
|
oldProps.intersect(newProps);
|
|
newProps.subtract(oldProps);
|
|
newProps2.subtract(newProps);
|
|
} else {
|
|
newProps2 = props.toSet();
|
|
}
|
|
|
|
bool b = this->blockSignals(true);
|
|
|
|
this->clear();
|
|
this->NewPropertyCount = newProps.size();
|
|
|
|
if (View == FlatView) {
|
|
QCMakePropertyList newP = newProps.toList();
|
|
QCMakePropertyList newP2 = newProps2.toList();
|
|
qSort(newP);
|
|
qSort(newP2);
|
|
int row_count = 0;
|
|
foreach (QCMakeProperty p, newP) {
|
|
this->insertRow(row_count);
|
|
this->setPropertyData(this->index(row_count, 0), p, true);
|
|
row_count++;
|
|
}
|
|
foreach (QCMakeProperty p, newP2) {
|
|
this->insertRow(row_count);
|
|
this->setPropertyData(this->index(row_count, 0), p, false);
|
|
row_count++;
|
|
}
|
|
} else if (this->View == GroupView) {
|
|
QMap<QString, QCMakePropertyList> newPropsTree;
|
|
this->breakProperties(newProps, newPropsTree);
|
|
QMap<QString, QCMakePropertyList> newPropsTree2;
|
|
this->breakProperties(newProps2, newPropsTree2);
|
|
|
|
QStandardItem* root = this->invisibleRootItem();
|
|
|
|
foreach (QString key, newPropsTree.keys()) {
|
|
QCMakePropertyList props2 = newPropsTree[key];
|
|
|
|
QList<QStandardItem*> parentItems;
|
|
parentItems.append(
|
|
new QStandardItem(key.isEmpty() ? tr("Ungrouped Entries") : key));
|
|
parentItems.append(new QStandardItem());
|
|
parentItems[0]->setData(QBrush(QColor(255, 100, 100)),
|
|
Qt::BackgroundColorRole);
|
|
parentItems[1]->setData(QBrush(QColor(255, 100, 100)),
|
|
Qt::BackgroundColorRole);
|
|
parentItems[0]->setData(1, GroupRole);
|
|
parentItems[1]->setData(1, GroupRole);
|
|
root->appendRow(parentItems);
|
|
|
|
int num = props2.size();
|
|
for (int i = 0; i < num; i++) {
|
|
QCMakeProperty prop = props2[i];
|
|
QList<QStandardItem*> items;
|
|
items.append(new QStandardItem());
|
|
items.append(new QStandardItem());
|
|
parentItems[0]->appendRow(items);
|
|
this->setPropertyData(this->indexFromItem(items[0]), prop, true);
|
|
}
|
|
}
|
|
|
|
foreach (QString key, newPropsTree2.keys()) {
|
|
QCMakePropertyList props2 = newPropsTree2[key];
|
|
|
|
QStandardItem* parentItem =
|
|
new QStandardItem(key.isEmpty() ? tr("Ungrouped Entries") : key);
|
|
root->appendRow(parentItem);
|
|
parentItem->setData(1, GroupRole);
|
|
|
|
int num = props2.size();
|
|
for (int i = 0; i < num; i++) {
|
|
QCMakeProperty prop = props2[i];
|
|
QList<QStandardItem*> items;
|
|
items.append(new QStandardItem());
|
|
items.append(new QStandardItem());
|
|
parentItem->appendRow(items);
|
|
this->setPropertyData(this->indexFromItem(items[0]), prop, false);
|
|
}
|
|
}
|
|
}
|
|
|
|
this->blockSignals(b);
|
|
this->reset();
|
|
}
|
|
|
|
QCMakeCacheModel::ViewType QCMakeCacheModel::viewType() const
|
|
{
|
|
return this->View;
|
|
}
|
|
|
|
void QCMakeCacheModel::setViewType(QCMakeCacheModel::ViewType t)
|
|
{
|
|
this->View = t;
|
|
|
|
QCMakePropertyList props = this->properties();
|
|
QCMakePropertyList oldProps;
|
|
int numNew = this->NewPropertyCount;
|
|
int numTotal = props.count();
|
|
for (int i = numNew; i < numTotal; i++) {
|
|
oldProps.append(props[i]);
|
|
}
|
|
|
|
bool b = this->blockSignals(true);
|
|
this->clear();
|
|
this->setProperties(oldProps);
|
|
this->setProperties(props);
|
|
this->blockSignals(b);
|
|
this->reset();
|
|
}
|
|
|
|
void QCMakeCacheModel::setPropertyData(const QModelIndex& idx1,
|
|
const QCMakeProperty& prop, bool isNew)
|
|
{
|
|
QModelIndex idx2 = idx1.sibling(idx1.row(), 1);
|
|
|
|
this->setData(idx1, prop.Key, Qt::DisplayRole);
|
|
this->setData(idx1, prop.Help, QCMakeCacheModel::HelpRole);
|
|
this->setData(idx1, prop.Type, QCMakeCacheModel::TypeRole);
|
|
this->setData(idx1, prop.Advanced, QCMakeCacheModel::AdvancedRole);
|
|
|
|
if (prop.Type == QCMakeProperty::BOOL) {
|
|
int check = prop.Value.toBool() ? Qt::Checked : Qt::Unchecked;
|
|
this->setData(idx2, check, Qt::CheckStateRole);
|
|
} else {
|
|
this->setData(idx2, prop.Value, Qt::DisplayRole);
|
|
}
|
|
this->setData(idx2, prop.Help, QCMakeCacheModel::HelpRole);
|
|
|
|
if (!prop.Strings.isEmpty()) {
|
|
this->setData(idx1, prop.Strings, QCMakeCacheModel::StringsRole);
|
|
}
|
|
|
|
if (isNew) {
|
|
this->setData(idx1, QBrush(QColor(255, 100, 100)),
|
|
Qt::BackgroundColorRole);
|
|
this->setData(idx2, QBrush(QColor(255, 100, 100)),
|
|
Qt::BackgroundColorRole);
|
|
}
|
|
}
|
|
|
|
void QCMakeCacheModel::getPropertyData(const QModelIndex& idx1,
|
|
QCMakeProperty& prop) const
|
|
{
|
|
QModelIndex idx2 = idx1.sibling(idx1.row(), 1);
|
|
|
|
prop.Key = this->data(idx1, Qt::DisplayRole).toString();
|
|
prop.Help = this->data(idx1, HelpRole).toString();
|
|
prop.Type = static_cast<QCMakeProperty::PropertyType>(
|
|
this->data(idx1, TypeRole).toInt());
|
|
prop.Advanced = this->data(idx1, AdvancedRole).toBool();
|
|
prop.Strings =
|
|
this->data(idx1, QCMakeCacheModel::StringsRole).toStringList();
|
|
if (prop.Type == QCMakeProperty::BOOL) {
|
|
int check = this->data(idx2, Qt::CheckStateRole).toInt();
|
|
prop.Value = check == Qt::Checked;
|
|
} else {
|
|
prop.Value = this->data(idx2, Qt::DisplayRole).toString();
|
|
}
|
|
}
|
|
|
|
QString QCMakeCacheModel::prefix(const QString& s)
|
|
{
|
|
QString prefix = s.section('_', 0, 0);
|
|
if (prefix == s) {
|
|
prefix = QString();
|
|
}
|
|
return prefix;
|
|
}
|
|
|
|
void QCMakeCacheModel::breakProperties(
|
|
const QSet<QCMakeProperty>& props, QMap<QString, QCMakePropertyList>& result)
|
|
{
|
|
QMap<QString, QCMakePropertyList> tmp;
|
|
// return a map of properties grouped by prefixes, and sorted
|
|
foreach (QCMakeProperty p, props) {
|
|
QString prefix = QCMakeCacheModel::prefix(p.Key);
|
|
tmp[prefix].append(p);
|
|
}
|
|
// sort it and re-org any properties with only one sub item
|
|
QCMakePropertyList reorgProps;
|
|
QMap<QString, QCMakePropertyList>::iterator iter;
|
|
for (iter = tmp.begin(); iter != tmp.end();) {
|
|
if (iter->count() == 1) {
|
|
reorgProps.append((*iter)[0]);
|
|
iter = tmp.erase(iter);
|
|
} else {
|
|
qSort(*iter);
|
|
++iter;
|
|
}
|
|
}
|
|
if (reorgProps.count()) {
|
|
tmp[QString()] += reorgProps;
|
|
}
|
|
result = tmp;
|
|
}
|
|
|
|
QCMakePropertyList QCMakeCacheModel::properties() const
|
|
{
|
|
QCMakePropertyList props;
|
|
|
|
if (!this->rowCount()) {
|
|
return props;
|
|
}
|
|
|
|
QList<QModelIndex> idxs;
|
|
idxs.append(this->index(0, 0));
|
|
|
|
// walk the entire model for property entries
|
|
// this works regardless of a flat view or a tree view
|
|
while (!idxs.isEmpty()) {
|
|
QModelIndex idx = idxs.last();
|
|
if (this->hasChildren(idx) && this->rowCount(idx)) {
|
|
idxs.append(this->index(0, 0, idx));
|
|
} else {
|
|
if (!data(idx, GroupRole).toInt()) {
|
|
// get data
|
|
QCMakeProperty prop;
|
|
this->getPropertyData(idx, prop);
|
|
props.append(prop);
|
|
}
|
|
|
|
// go to the next in the tree
|
|
while (!idxs.isEmpty() &&
|
|
(
|
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) && \
|
|
QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
|
(idxs.last().row() + 1) >= rowCount(idxs.last().parent()) ||
|
|
#endif
|
|
!idxs.last().sibling(idxs.last().row() + 1, 0).isValid())) {
|
|
idxs.removeLast();
|
|
}
|
|
if (!idxs.isEmpty()) {
|
|
idxs.last() = idxs.last().sibling(idxs.last().row() + 1, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
return props;
|
|
}
|
|
|
|
bool QCMakeCacheModel::insertProperty(QCMakeProperty::PropertyType t,
|
|
const QString& name,
|
|
const QString& description,
|
|
const QVariant& value, bool advanced)
|
|
{
|
|
QCMakeProperty prop;
|
|
prop.Key = name;
|
|
prop.Value = value;
|
|
prop.Help = description;
|
|
prop.Type = t;
|
|
prop.Advanced = advanced;
|
|
|
|
// insert at beginning
|
|
this->insertRow(0);
|
|
this->setPropertyData(this->index(0, 0), prop, true);
|
|
this->NewPropertyCount++;
|
|
return true;
|
|
}
|
|
|
|
void QCMakeCacheModel::setEditEnabled(bool e)
|
|
{
|
|
this->EditEnabled = e;
|
|
}
|
|
|
|
bool QCMakeCacheModel::editEnabled() const
|
|
{
|
|
return this->EditEnabled;
|
|
}
|
|
|
|
int QCMakeCacheModel::newPropertyCount() const
|
|
{
|
|
return this->NewPropertyCount;
|
|
}
|
|
|
|
Qt::ItemFlags QCMakeCacheModel::flags(const QModelIndex& idx) const
|
|
{
|
|
Qt::ItemFlags f = QStandardItemModel::flags(idx);
|
|
if (!this->EditEnabled) {
|
|
f &= ~Qt::ItemIsEditable;
|
|
return f;
|
|
}
|
|
if (QCMakeProperty::BOOL == this->data(idx, TypeRole).toInt()) {
|
|
f |= Qt::ItemIsUserCheckable;
|
|
}
|
|
return f;
|
|
}
|
|
|
|
QModelIndex QCMakeCacheModel::buddy(const QModelIndex& idx) const
|
|
{
|
|
if (!this->hasChildren(idx) &&
|
|
this->data(idx, TypeRole).toInt() != QCMakeProperty::BOOL) {
|
|
return this->index(idx.row(), 1, idx.parent());
|
|
}
|
|
return idx;
|
|
}
|
|
|
|
QCMakeCacheModelDelegate::QCMakeCacheModelDelegate(QObject* p)
|
|
: QItemDelegate(p)
|
|
, FileDialogFlag(false)
|
|
{
|
|
}
|
|
|
|
void QCMakeCacheModelDelegate::setFileDialogFlag(bool f)
|
|
{
|
|
this->FileDialogFlag = f;
|
|
}
|
|
|
|
QWidget* QCMakeCacheModelDelegate::createEditor(
|
|
QWidget* p, const QStyleOptionViewItem& /*option*/,
|
|
const QModelIndex& idx) const
|
|
{
|
|
QModelIndex var = idx.sibling(idx.row(), 0);
|
|
int type = var.data(QCMakeCacheModel::TypeRole).toInt();
|
|
if (type == QCMakeProperty::BOOL) {
|
|
return CM_NULLPTR;
|
|
}
|
|
if (type == QCMakeProperty::PATH) {
|
|
QCMakePathEditor* editor =
|
|
new QCMakePathEditor(p, var.data(Qt::DisplayRole).toString());
|
|
QObject::connect(editor, SIGNAL(fileDialogExists(bool)), this,
|
|
SLOT(setFileDialogFlag(bool)));
|
|
return editor;
|
|
}
|
|
if (type == QCMakeProperty::FILEPATH) {
|
|
QCMakeFilePathEditor* editor =
|
|
new QCMakeFilePathEditor(p, var.data(Qt::DisplayRole).toString());
|
|
QObject::connect(editor, SIGNAL(fileDialogExists(bool)), this,
|
|
SLOT(setFileDialogFlag(bool)));
|
|
return editor;
|
|
}
|
|
if (type == QCMakeProperty::STRING &&
|
|
var.data(QCMakeCacheModel::StringsRole).isValid()) {
|
|
QCMakeComboBox* editor = new QCMakeComboBox(
|
|
p, var.data(QCMakeCacheModel::StringsRole).toStringList());
|
|
editor->setFrame(false);
|
|
return editor;
|
|
}
|
|
|
|
QLineEdit* editor = new QLineEdit(p);
|
|
editor->setFrame(false);
|
|
return editor;
|
|
}
|
|
|
|
bool QCMakeCacheModelDelegate::editorEvent(QEvent* e,
|
|
QAbstractItemModel* model,
|
|
const QStyleOptionViewItem& option,
|
|
const QModelIndex& index)
|
|
{
|
|
Qt::ItemFlags flags = model->flags(index);
|
|
if (!(flags & Qt::ItemIsUserCheckable) ||
|
|
!(option.state & QStyle::State_Enabled) ||
|
|
!(flags & Qt::ItemIsEnabled)) {
|
|
return false;
|
|
}
|
|
|
|
QVariant value = index.data(Qt::CheckStateRole);
|
|
if (!value.isValid()) {
|
|
return false;
|
|
}
|
|
|
|
if ((e->type() == QEvent::MouseButtonRelease) ||
|
|
(e->type() == QEvent::MouseButtonDblClick)) {
|
|
// eat the double click events inside the check rect
|
|
if (e->type() == QEvent::MouseButtonDblClick) {
|
|
return true;
|
|
}
|
|
} else if (e->type() == QEvent::KeyPress) {
|
|
if (static_cast<QKeyEvent*>(e)->key() != Qt::Key_Space &&
|
|
static_cast<QKeyEvent*>(e)->key() != Qt::Key_Select) {
|
|
return false;
|
|
}
|
|
} else {
|
|
return false;
|
|
}
|
|
|
|
Qt::CheckState state =
|
|
(static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked ? Qt::Unchecked
|
|
: Qt::Checked);
|
|
bool success = model->setData(index, state, Qt::CheckStateRole);
|
|
if (success) {
|
|
this->recordChange(model, index);
|
|
}
|
|
return success;
|
|
}
|
|
|
|
// Issue 205903 fixed in Qt 4.5.0.
|
|
// Can remove this function and FileDialogFlag when minimum Qt version is 4.5
|
|
bool QCMakeCacheModelDelegate::eventFilter(QObject* object, QEvent* evt)
|
|
{
|
|
// workaround for what looks like a bug in Qt on Mac OS X
|
|
// where it doesn't create a QWidget wrapper for the native file dialog
|
|
// so the Qt library ends up assuming the focus was lost to something else
|
|
|
|
if (evt->type() == QEvent::FocusOut && this->FileDialogFlag) {
|
|
return false;
|
|
}
|
|
return QItemDelegate::eventFilter(object, evt);
|
|
}
|
|
|
|
void QCMakeCacheModelDelegate::setModelData(QWidget* editor,
|
|
QAbstractItemModel* model,
|
|
const QModelIndex& index) const
|
|
{
|
|
QItemDelegate::setModelData(editor, model, index);
|
|
const_cast<QCMakeCacheModelDelegate*>(this)->recordChange(model, index);
|
|
}
|
|
|
|
QSize QCMakeCacheModelDelegate::sizeHint(const QStyleOptionViewItem& option,
|
|
const QModelIndex& index) const
|
|
{
|
|
QSize sz = QItemDelegate::sizeHint(option, index);
|
|
QStyle* style = QApplication::style();
|
|
|
|
// increase to checkbox size
|
|
QStyleOptionButton opt;
|
|
opt.QStyleOption::operator=(option);
|
|
sz = sz.expandedTo(
|
|
style->subElementRect(QStyle::SE_ViewItemCheckIndicator, &opt, CM_NULLPTR)
|
|
.size());
|
|
|
|
return sz;
|
|
}
|
|
|
|
QSet<QCMakeProperty> QCMakeCacheModelDelegate::changes() const
|
|
{
|
|
return mChanges;
|
|
}
|
|
|
|
void QCMakeCacheModelDelegate::clearChanges()
|
|
{
|
|
mChanges.clear();
|
|
}
|
|
|
|
void QCMakeCacheModelDelegate::recordChange(QAbstractItemModel* model,
|
|
const QModelIndex& index)
|
|
{
|
|
QModelIndex idx = index;
|
|
QAbstractItemModel* mymodel = model;
|
|
while (qobject_cast<QAbstractProxyModel*>(mymodel)) {
|
|
idx = static_cast<QAbstractProxyModel*>(mymodel)->mapToSource(idx);
|
|
mymodel = static_cast<QAbstractProxyModel*>(mymodel)->sourceModel();
|
|
}
|
|
QCMakeCacheModel* cache_model = qobject_cast<QCMakeCacheModel*>(mymodel);
|
|
if (cache_model && idx.isValid()) {
|
|
QCMakeProperty prop;
|
|
idx = idx.sibling(idx.row(), 0);
|
|
cache_model->getPropertyData(idx, prop);
|
|
|
|
// clean out an old one
|
|
QSet<QCMakeProperty>::iterator iter = mChanges.find(prop);
|
|
if (iter != mChanges.end()) {
|
|
mChanges.erase(iter);
|
|
}
|
|
// now add the new item
|
|
mChanges.insert(prop);
|
|
}
|
|
}
|