324 lines
8.9 KiB
C++
324 lines
8.9 KiB
C++
#include "qcd_kmodel.h"
|
|
#include "cdutils_k.h"
|
|
#include "piqt.h"
|
|
#include <QDebug>
|
|
#include <QBrush>
|
|
#include <QColor>
|
|
#include "qvariantedit.h"
|
|
#include "qad_types.h"
|
|
|
|
|
|
using namespace CDUtils;
|
|
|
|
|
|
CDKItemModel::CDKItemModel(QObject *parent) : QAbstractItemModel(parent) {
|
|
root = 0;
|
|
internalRebuild();
|
|
}
|
|
|
|
|
|
CDKItemModel::~CDKItemModel() {
|
|
delete root;
|
|
}
|
|
|
|
|
|
QVariant CDKItemModel::data(const QModelIndex &index, int role) const {
|
|
if (!index.isValid()) return QVariant();
|
|
CDKItem *item = getItem(index);
|
|
return item->data(index.column(), role);
|
|
}
|
|
|
|
|
|
QVariant CDKItemModel::headerData(int section, Qt::Orientation orientation, int role) const {
|
|
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
|
|
switch (section) {
|
|
case 0: return trUtf8("Index");
|
|
case 1: return trUtf8("Name");
|
|
case 2: return trUtf8("Type");
|
|
case 3: return trUtf8("Expression");
|
|
case 4: return trUtf8("Value");
|
|
case 5: return trUtf8("Comment");
|
|
}
|
|
}
|
|
return QVariant();
|
|
}
|
|
|
|
|
|
QModelIndex CDKItemModel::index(int row, int column, const QModelIndex &parent) const {
|
|
if (parent.isValid() && parent.column() != 0) return QModelIndex();
|
|
CDKItem * p = getItem(parent);
|
|
CDKItem * c = p->childs.value(row, 0);
|
|
if (c) return createIndex(row, column, c);
|
|
else return QModelIndex();
|
|
}
|
|
|
|
|
|
QModelIndex CDKItemModel::parent(const QModelIndex &index) const {
|
|
if (!index.isValid()) return QModelIndex();
|
|
CDKItem * c = getItem(index);
|
|
CDKItem * p = c->parent_;
|
|
if (p == root) return QModelIndex();
|
|
return createIndex(p->parent_->childs.indexOf(p), 0, p);
|
|
}
|
|
|
|
|
|
int CDKItemModel::rowCount(const QModelIndex &parent) const {
|
|
CDKItem *p = getItem(parent);
|
|
return p->childs.count();
|
|
}
|
|
|
|
|
|
int CDKItemModel::columnCount(const QModelIndex &parent) const {
|
|
return 6;
|
|
}
|
|
|
|
|
|
Qt::ItemFlags CDKItemModel::flags(const QModelIndex & index) const {
|
|
if (!index.isValid()) return 0;
|
|
Qt::ItemFlags f = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
|
CDKItem * item = getItem(index);
|
|
if ((index.column() == 3 || index.column() == 4) && item->type_ == CDKItem::ItemCDType) f |= Qt::ItemIsEditable;
|
|
if (item->type_ == CDKItem::ItemCDType && index.column() == 4) {
|
|
CDType t = K.section(item->buildPath())[item->index_];
|
|
if (t.type() == "b") {
|
|
f |= Qt::ItemIsUserCheckable;
|
|
// piCout << "ItemIsUserCheckable";
|
|
}
|
|
}
|
|
return f;
|
|
}
|
|
|
|
|
|
bool CDKItemModel::setData(const QModelIndex & index, const QVariant &value, int role) {
|
|
if (role == Qt::CheckStateRole && index.column() == 4) {
|
|
CDKItem * item = getItem(index);
|
|
if (item->type_ == CDKItem::ItemCDType) {
|
|
CDType t = K.section(item->buildPath())[item->index_];
|
|
if (t.type() == "b") {
|
|
bool result = item->setData(index.column(), PI2QString(PIString::fromBool(value.toBool())));
|
|
QModelIndex rin(CDKItemModel::index(index.row(), 3, index.parent()));
|
|
emit dataChanged(rin, rin);
|
|
return result;
|
|
}
|
|
}
|
|
}
|
|
if (role != Qt::EditRole) return false;
|
|
CDKItem * item = getItem(index);
|
|
bool result = item->setData(index.column(), value);
|
|
if (result) {
|
|
QModelIndex rin(CDKItemModel::index(index.row(), 3, index.parent()));
|
|
emit dataChanged(rin, rin);
|
|
emit dataChanged(index, index);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
void CDKItemModel::rebuildModel() {
|
|
beginResetModel();
|
|
internalRebuild();
|
|
endResetModel();
|
|
}
|
|
|
|
|
|
void CDKItemModel::buildItem(CDKItem *it, CDSection & r) {
|
|
//piCout << "build item" << r.name << r.alias;
|
|
PIMap<int, CDType>::iterator i;
|
|
for (i = r.k.begin(); i != r.k.end(); ++i) {
|
|
it->childs << new CDKItem(i.key(), CDKItem::ItemCDType, it);
|
|
}
|
|
PIMap<int, CDSection>::iterator j;
|
|
for (j = r.s.begin(); j != r.s.end(); ++j) {
|
|
it->childs << new CDKItem(j.key(), CDKItem::ItemCDSection, it);
|
|
buildItem(it->childs.back(), j.value());
|
|
}
|
|
}
|
|
|
|
|
|
void CDKItemModel::updateModel() {
|
|
beginResetModel();
|
|
endResetModel();
|
|
}
|
|
|
|
|
|
void CDKItemModel::internalRebuild() {
|
|
//qDebug() << "[CDKItemModel]" << "internalRebuild()";
|
|
if (root) delete root;
|
|
root = new CDKItem(0, CDKItem::ItemCDSection, 0);
|
|
CDSection & r = K.root();
|
|
buildItem(root, r);
|
|
}
|
|
|
|
|
|
CDKItem * CDKItemModel::getItem(const QModelIndex &index) const {
|
|
if (index.isValid()) {
|
|
CDKItem * item = static_cast<CDKItem*>(index.internalPointer());
|
|
if (item) return item;
|
|
}
|
|
return root;
|
|
}
|
|
|
|
|
|
// CDKItem
|
|
|
|
CDKItem::CDKItem(int index, CDKItem::CDKItemType type, CDKItem *parent) {
|
|
index_ = index;
|
|
parent_ = parent;
|
|
type_ = type;
|
|
}
|
|
|
|
|
|
CDKItem::~CDKItem() {
|
|
qDeleteAll(childs);
|
|
}
|
|
|
|
|
|
QVariant CDKItem::data(int column, int role) const {
|
|
if (role == Qt::BackgroundRole) {
|
|
switch (type_) {
|
|
case ItemCDType: {
|
|
CDType & t = K.section(buildPath())[index_];
|
|
if (t.errorString().isEmpty()) return QBrush(QColor(255, 250, 230));
|
|
else return QBrush(QColor(255, 128, 128));
|
|
}
|
|
case ItemCDSection: return QBrush(QColor(230, 250, 230));
|
|
}
|
|
}
|
|
if (role == Qt::CheckStateRole && type_ == ItemCDType && column == 4) {
|
|
CDType & t = K.section(buildPath())[index_];
|
|
if (t.type() == "b") return t.toBool() ? Qt::Checked : Qt::Unchecked;
|
|
else QVariant();
|
|
}
|
|
if (role == Qt::ToolTipRole && type_ == ItemCDType) {
|
|
CDType & t = K.section(buildPath())[index_];
|
|
return PI2QString(t.errorString());
|
|
}
|
|
if (role != Qt::DisplayRole && role != Qt::EditRole) return QVariant();
|
|
PIDeque<int> path = buildPath();
|
|
CDSection & rs = K.section(path);
|
|
CDSection s;
|
|
switch (type_) {
|
|
case ItemCDType:
|
|
switch (column) {
|
|
case 0: return QString::number(index_);
|
|
case 1: return PI2QString(rs[index_].name());
|
|
case 2: return stringType(rs[index_].type());
|
|
case 3: return PI2QString(rs[index_].formula());
|
|
case 4: return value(rs[index_], role);
|
|
case 5: return PI2QString(rs[index_].comment());
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case ItemCDSection:
|
|
s = rs.section(index_);
|
|
// piCout << rs.name << rs.alias << s.name << s.alias;
|
|
switch (column) {
|
|
case 0: return QString("[") + QString::number(index_) + QString("]");
|
|
case 1: return PI2QString(s.alias);
|
|
case 2: return PI2QString(s.name);
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
return QVariant();
|
|
}
|
|
|
|
|
|
QVariant CDKItem::value(CDType t, int role) const {
|
|
if (t.type() == "f") return t.toDouble();
|
|
if (t.type() == "n") return t.toInt();
|
|
if (t.type() == "b") return t.toBool();
|
|
if (t.type() == "e") {
|
|
QAD::Enum et = PI2QADEnum(t.enumValues());
|
|
et.selectValue(t.toInt());
|
|
if (role == Qt::EditRole) return QVariant::fromValue<QAD::Enum>(et);
|
|
else return et.selectedName();
|
|
}
|
|
return PI2QString(t.value());
|
|
}
|
|
|
|
|
|
bool CDKItem::setData(int column, const QVariant &value) {
|
|
if ((column == 3 || column == 4) && type_ == ItemCDType) {
|
|
K.section(buildPath())[index_].setValue(Q2PIString(value.toString()));
|
|
K.calculate();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
PIDeque<int> CDKItem::buildPath() const {
|
|
PIDeque<int> path;
|
|
CDKItem * p = parent_;
|
|
while (p) {
|
|
path.push_front(p->index_);
|
|
p = p->parent_;
|
|
}
|
|
path.take_front();
|
|
return path;
|
|
}
|
|
|
|
|
|
QString CDKItem::stringType(const PIString & t) const {
|
|
QString n = PI2QString(t);
|
|
if (n.isEmpty()) return QString("");
|
|
switch (n[0].toLatin1()) {
|
|
case 'l': return QString("list"); break;
|
|
case 'b': return QString("bool"); break;
|
|
case 'n': return QString("int"); break;
|
|
case 'f': return QString("double"); break;
|
|
case 'c': return QString("color"); break;
|
|
case 'r': return QString("rect"); break;
|
|
case 'a': return QString("rect"); break;
|
|
case 'p': return QString("point"); break;
|
|
case 'v': return QString("vector"); break;
|
|
case 'i': return QString("IP"); break;
|
|
case 'e': return QString("enum"); break;
|
|
case 'F': return QString("file"); break;
|
|
case 'D': return QString("dir"); break;
|
|
}
|
|
return QString("double");
|
|
}
|
|
|
|
|
|
// CDKDelegate
|
|
|
|
CDKDelegate::CDKDelegate(QObject *parent) : QStyledItemDelegate(parent) {
|
|
}
|
|
|
|
|
|
QWidget *CDKDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const {
|
|
return new QVariantEdit(parent);
|
|
}
|
|
|
|
|
|
void CDKDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const {
|
|
QVariantEdit *edit = static_cast<QVariantEdit*>(editor);
|
|
edit->setValue(index.model()->data(index, Qt::EditRole));
|
|
}
|
|
|
|
|
|
void CDKDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const {
|
|
QVariantEdit *edit = static_cast<QVariantEdit*>(editor);
|
|
QVariant v = edit->value();
|
|
if (v.canConvert<QAD::Enum>()) {
|
|
QAD::Enum et = v.value<QAD::Enum>();
|
|
model->setData(index, et.selectedValue(), Qt::EditRole);
|
|
} else model->setData(index, v, Qt::EditRole);
|
|
}
|
|
|
|
|
|
void CDKDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const {
|
|
editor->setGeometry(option.rect);
|
|
}
|
|
|
|
|
|
QSize CDKDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const {
|
|
QSize s = QStyledItemDelegate::sizeHint(option, index);
|
|
s.setWidth(s.width() + 20);
|
|
return s;
|
|
}
|