mirror of
https://github.com/reactos/CMake.git
synced 2025-01-07 11:40:23 +00:00
96afb12087
This converts the CMake license to a pure 3-clause OSI-approved BSD License. We drop the previous license clause requiring modified versions to be plainly marked. We also update the CMake copyright to cover the full development time range.
716 lines
18 KiB
C++
716 lines
18 KiB
C++
/*============================================================================
|
|
CMake - Cross Platform Makefile Generator
|
|
Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
|
|
|
|
Distributed under the OSI-approved BSD License (the "License");
|
|
see accompanying file Copyright.txt for details.
|
|
|
|
This software is distributed WITHOUT ANY WARRANTY; without even the
|
|
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
See the License for more information.
|
|
============================================================================*/
|
|
|
|
#include "QCMakeCacheView.h"
|
|
|
|
#include <QHBoxLayout>
|
|
#include <QHeaderView>
|
|
#include <QEvent>
|
|
#include <QStyle>
|
|
#include <QKeyEvent>
|
|
#include <QSortFilterProxyModel>
|
|
#include <QMetaProperty>
|
|
#include <QApplication>
|
|
|
|
#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
|
|
{
|
|
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
|
|
{
|
|
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();
|
|
if(!adv || (adv && this->ShowAdvanced))
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// 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);
|
|
}
|
|
else 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)
|
|
{
|
|
QStringList labels;
|
|
labels << tr("Name") << tr("Value");
|
|
this->setHorizontalHeaderLabels(labels);
|
|
}
|
|
|
|
QCMakeCacheModel::~QCMakeCacheModel()
|
|
{
|
|
}
|
|
|
|
static uint qHash(const QCMakeProperty& p)
|
|
{
|
|
return qHash(p.Key);
|
|
}
|
|
|
|
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 = props.toSet();
|
|
QSet<QCMakeProperty> newProps2 = newProps;
|
|
QSet<QCMakeProperty> oldProps = this->properties().toSet();
|
|
|
|
oldProps.intersect(newProps);
|
|
newProps.subtract(oldProps);
|
|
newProps2.subtract(newProps);
|
|
|
|
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);
|
|
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);
|
|
|
|
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
|
|
{
|
|
// get data
|
|
QCMakeProperty prop;
|
|
this->getPropertyData(idx, prop);
|
|
props.append(prop);
|
|
|
|
// go to the next in the tree
|
|
while(!idxs.isEmpty() && !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&, const QModelIndex& idx) const
|
|
{
|
|
QModelIndex var = idx.sibling(idx.row(), 0);
|
|
int type = var.data(QCMakeCacheModel::TypeRole).toInt();
|
|
if(type == QCMakeProperty::BOOL)
|
|
{
|
|
return NULL;
|
|
}
|
|
else 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;
|
|
}
|
|
else 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;
|
|
}
|
|
else 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, NULL).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);
|
|
}
|
|
}
|
|
|